《深入理解java虚拟机》学习笔记05--HotSpot中对象存活判读算法和垃圾收集算法的实现

来源:互联网 发布:网络黑侠新书 编辑:程序博客网 时间:2024/05/17 13:05

 HotSopt虚拟机如何发起内存回收

 1、枚举根节点

 问题:(1)从可达性分析中从GC Roots节点找到引用,很耗时间。

            (2)可达性分析对执行时间的敏感还体现在GC停顿上。即gc进行时,必须停顿所有的java执行线程,这样是为了保持”一致性“。

 解决办法:目前主流的java虚拟机都是使用的准确是GC(即虚拟机知道内存中某个位置的数据具体是什么类型),所以当执行系统停顿下来后,并不需要一个不漏的检查完所有执行上下文和全局的引用位置。虚拟机应当是有办法直接得知哪些地方存放对象的引用。

    在HotSpot的实现中,是使用一组成为OopMap的数据结构来达到目的的:

        在类加载的时候,HotSpot就把对象内什么偏移量上式什么类型的数据计算出来。

        在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用。

2、安全点(Safepoint)

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

问题:(1)可能导致引用关系的变化

     (2)如果为每一天令都生成OopMap,将会需要大量的额外空间。

解决:虚拟机并没有为每条指令都生成OopMap,只在”特定的位置“记录了这些信息,这些位置称为安全点(Safepoint),即程序执行时并非在所有地方都能停顿下来开始GC,只能在到达安全点时才能暂停。

safepoint的选定:

   太少让GC等待时间过长,太多导致过分增大运行时的负荷,所以安全点的选定基本上都是以程序”是否具有让程序长时间执行的特征“为标准选定的,长时间执行的最明显特征就是指令序列的复用,例如方法调用,循环跳转、异常跳转等。所以这些功能的指令才会产生安全点。


  对于安全点,另一个需要考虑的问题是:如何让GC发生时让所有线程(不包括执行JNI调用的线程)都跑到最近的安全点时停顿下来。有两种解决方案:抢先式中断(PreemptiveSuspension)和主动式中断(Voluntary Suspension)

  抢先式中断:不需要线程执行的代码主动配合,在GC发生时,首先把所有的线程全部中断,如果发现线程中断的地方不在安全点上,就恢复线程,让他跑到安全点。现在几乎虚拟机用它。

  主动式中断:当GC需要中断线程的时候,不直接对线程操作,仅仅简单的设置一个标志,各个线程执行时主动去轮询这个标志,发现指端标志为真就自己中断挂起。轮询标志的地方结合安全点位置重合,另外在加上创建对象需要分配内存的地方。

3、安全区域

   安全区域是指一段代码片段之后,引用关系不会发生变化。在这个区域中的任意位置开始GC都是安全的。

   在线程执行到Safe Region中的代码片段时,受限标识自己已经进入了Safe Region ,那样,当这段时间里JVM要发起GC是,就不用管标识自己为Safe Region状态的线程了。

    在线程要离开安全区域时,他要检查系统是否已经完成了根节点的枚举,如果完成了,那线程就继续执行,否则他就必须等待直到收到可以安全离开安全区域的信号为止。

阅读全文
0 0
原创粉丝点击