JVM垃圾回收算法实现
在JVM对垃圾进行回收的时候,需要对对象进行判断是否还“存活”,因为进行回收的时候需要保证在一致性的快照上进行,需要停顿下来进行垃圾回收。
1.如果对逐渐检查这里边的引用的话,那么必然会消耗大量的时间,怎么去减少这个时间呢?
目前大部分java虚拟机使用的是准确式GC,这样当执行系统停顿下来,并不需要一个不漏地检查完有执行上下文和全局的引用位置。在HotSpot虚拟机中,是使用一种OopMap的数据结构来达到这个目的(从外部记录下来类型信息,存成映射表),在类加载的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译的时候也会在特定的位置记录下栈和寄存器中那些位置是可用的。这样GC扫描的时候就可以直接得知这些信息了。
2.那么线程应该停在哪里呢?
OopMap内容变化的指令非常多,如果为每一条指令都生成对应的的OopMap(即在每个时间点都做映射),这样的消耗是非常大的。
所以HotSpot也没有这样做,只是在特定的位置做了映射,这些位置称为安全点。程序需要暂停在安全点。
3.安全点应该怎么设置?
安全点太多GC会太频繁,安全点太少又会导致GC等待时间太长。
安全点一般设置位置:
- 循环的末尾
- 函数返回之前
- 调用方法之后
- 抛出异常的位置
4.怎么让所有线程暂停在安全点上?
1:抢先式中断:
当GC发生时,中断所有线程,判断线程是不是停在了安全点,如果不是则恢复线程,让他跑到安全点再暂停。但是现在几乎没有虚拟机实现采用抢先式中断来暂停线程从而响应GC事件了。
2:主动式中断:
主动式中断不直接对线程进行操作,仅仅设置一个标志,各个线程执行时主动去轮询这个标志,如果标志为真的话,那么开始中断线程。轮询的标志和安全点是重合的。
5.对于”不执行的程序“如何进行垃圾回收?
”不执行的程序“:指线程处于Sleep或者Blocked状态,这时候无法影响JVM的中断请求。
这个时候需要用安全区来解决。
安全区域是指在一段代码片段之中,引用关系不会发生变化,在这个区域任何地方开启GC都是安全的。
当线程执行到安全区的代码时,首先标识自己已经进入了安全区,当这段时间里jvm要发起GC时就不用管标识自己为安全区状态的线程了,当线程要离开,要检查系统是否已经完成了GC,如果完成了线程继续执行,否则他需要等待收到可以安全离开的信号为止。
还没有评论,来说两句吧...