枚举根节点、安全点、安全区域、OopMap


对象存活判定算法和垃圾收集算法

3.4.1 枚举根节点

使用一组称为OopMap的数据解构来完成枚举根节点;

枚举根节点即为GC Roots的一个枚举;
GC Roots中节点++一般++为全局性引用(常量、类静态属性)栈帧中的本地变量表

具体的GC Roots(了解)

  1. 虚拟机栈(栈桢中的 局部变量表中的 本地变量表)中的引用的对象
  2. 方法区中的 类的静态属性 引用的对象
  3. 方法区中的常量引用的对象
  4. 本地方法栈中JNI(Native方法)的引用的对象

枚举根节点的2个问题

    1. 如果逐一检查引用,则肯定消耗性能,所以不可能这么做
    1. 可达性分析中,不能出现分析对象过程中对象引用关系还在不断变化,这是导致GC停顿(Stop The World)的重要原因,枚举根节点是必须停顿的;

解决方法:使用OopMap数据解构

  • 类加载完成后,会把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译过程中,在特定的位置(即安全点)使用OopMap记录下栈和寄存器哪些位置是引用,这样GC在扫描时就可以直接得知这些信息了。

3.4.2 安全点

    在OopMap的协助下,HotSpot可以快速且准确地完成GC Roots枚举

安全点Safe Point:是指一些特定的位置,当线程运行到这些位置时,线程的一些状态可以被确定,比如记录OopMap的状态,从而确定GC Root的信息,使JVM可以安全的进行一些操作,比如开始GC。

    如果每条指令都生成OopMap那将需要大量的额外空间。此时在特定的位置上 (即安全点)使程序不是在所有的地方都停顿(Stop The World)下来开始GC,只有在到达安全点时才停顿开始GC

安全点的选取:

  1. 安全点的选定:不能使GC等待时间过长也不能使GC频繁触发,如具有方法调用、循环跳转、异常跳转的指令才会有安全点。

从线程角度看,safepoint可以理解成是在代码执行过程中的一些特殊位置,当线程执行到这些位置的时候,说明虚拟机当前的状态是安全的,如果有需要,可以在这个位置暂停

如何让GC发生的时候让所有线程都跑到”安全点“停下来。方式有两种:

  1. 抢先中断式(弃用):当发生GC时让所有线程都停下来,如果有线程没有到安全点,就让该线程继续跑到安全点
  2. 主动式抢断:当线程执行GC需要中断时,不需要对线程进行操作,而是设置一个标志位,各线程主动去轮询这个标志位。标志位和安全点在同一个位置,发现标志位为真是就将自己这个线程中断挂起

3.4.3 安全区域

安全区域是指一段代码段中引用关系不会发生变化,在该区域何时何地开始GC都是安全的。线程执行安全区域的代码块时会标识自己已经进入了安全区域,此时如果JVM发起GC线程不会再标志中断状态标识,线程离开安全区域时会检查GC枚举GC Roots根节点(或者是整个GC过程)是否已经完成,如果完成了就继续执行,没完成的话就等待GC完成回收任务收到可以离开的信号再离开安全区域。

猜你喜欢

转载自blog.csdn.net/qq_43369986/article/details/109009074