JVM - 解读GC中的 Safe Point & Safe Region

简介: JVM - 解读GC中的 Safe Point & Safe Region

20200704080655266.png

Safe Point 安全点


2020070408104642.png

思考: 如上图 GC的时候,是不是可以马上GC,而不用去care用户线程 ?


答案肯定是不行的。 HotSpot中GC不是在任意位置都可以进入,而只能在safepoint处进入。


JVM在设计的时候在“特定位置”记录了OopMap , 而这些位置被称为安全点。


简单来说


安全点就是指代码运行到这个地方,它的状态是确定的, JVM就可以安全的进行一些操作,比如GC。


所以GC不是想什么时候做就立即触发的,是需要等待所有线程运行到安全点后才能触发。


安全点主要解决的是如何停顿用户线程。


这些特定的安全点位置主要有以下几种:


  • 方法返回之前
  • 调用某个方法之后
  • 抛出异常的位置
  • 循环的末尾
  • …等等


安全点的选定的核心在于: 既不能太少 (太少的话用户线程一直在跑,跑不到SafePoint, 那就没法GC, 并且跑的过程中用户线程也会创建对象,也要占内存,本身需要GC,那就说明内存吃紧了) ,也不能太多 (太多太频繁就意味着运行时内存负荷较高) 。


第二个问题需要考虑: 如何在GC时让用户线程都跑到最近的安全点,然后停下来。 JVM 采取的方式是主动式终端,不直接线程操作,仅简单设置一个标志位,各个程序执行的时候去轮询这个标志,一旦返现中断标志位真就自己在最近的安全点上主动挂起。


轮询标志的地方和安全点是重合的。


既然是轮询,那必须得高效,HotSpot把轮询的操作精简到只有一条汇编指令的程度,使用的是内存保护陷阱的方式。


Safe Region 安全区域


安全似乎解决了如何停顿用户线程,让虚拟机进入GC状态的问题了。 但如果程序“不执行”呢?


举个例子,线程休眠 Thread.sleep(100_000) 休眠100秒,要等100秒才能运行到安全区域啊 ,这可咋玩? 或者用户状态Blocked了 ,这都不执行了,压根就没法跑到safe point点了。。。。。


JVM设计大神引入了 Safe Region 来解决类似问题。


Safe Region 是指在一段代码片段中,引用关系不会发生变化。在这个区域内的任意地方开始 GC 都是安全的。


当用户线程执行到安全区里的代码是,会先标识自己进入了安全区域,那GC的时候就不管这些已经声明自己在安全区域的线程了。


OopMap


GC 我们都知道是清理那些引用不可达的对象, 简单来说 JVM怎样才能够判断出所有位置上的数据是不是指向GC堆里的引用 ?


从外部记录下类型信息,存成映射表 , 这种数据结构被称为 OopMap 。


在HotSpot中,对象的类型信息里有记录自己的OopMap,记录了在该类型的对象内什么偏移量上是什么类型的数据。


oopMap是一个附加的信息,告诉你栈上哪个位置本来是个什么东西。


这个信息是在JIT编译时跟机器码一起产生的。因为只有编译器知道源代码跟产生的代码的对应关系。


每个方法可能会有好几个oopMap,就是根据safepoint把一个方法的代码分成几段,每一段代码一个oopMap,作用域自然也仅限于这一段代码。


循环中引用多个对象,肯定会有多个变量,编译后占据栈上的多个位置。那这段代码的oopMap就会包含多条记录。


每个被JIT编译过后的方法也会在一些特定的位置记录下OopMap,记录了执行到该方法的某条指令的时候,栈上和寄存器里哪些位置是引用。


这样GC在扫描栈的时候就会查询这些OopMap就知道哪里是引用了。这些特定的位置主要在:


1、循环的末尾

2、方法临返回前 / 调用方法的call指令后

3、可能抛异常的位置


这种位置被称为“安全点”(safepoint)。之所以要选择一些特定的位置来记录OopMap,是因为如果对每条指令(的位置)都记录OopMap的话,这些记录就会比较大,那么空间开销会显得不值得。


选用一些比较关键的点来记录就能有效的缩小需要记录的数据量,但仍然能达到区分引用的目的。


因此,HotSpot中GC不是在任意位置都可以进入,而只能在safepoint处进入。


相关文章
|
2月前
|
算法 网络协议 Java
【JVM】——GC垃圾回收机制(图解通俗易懂)
GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)
|
3月前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
4月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
188 3
|
4月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
181 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
4月前
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
4月前
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
104 0
|
6月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
6月前
|
存储 监控 算法
深入解析JVM内部结构及GC机制的实战应用
深入解析JVM内部结构及GC机制的实战应用
|
7月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
632 3
|
7月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
147 8