之前我们介绍了如何判断对象是否存活,并进行垃圾回收时相关的算法实现。我们根据这些来谈谈在HotSpot中对这些算法实现时还需要经过哪些要求来保证算法高效的执行。
首先我们来看一张图:该图以可达性分析算法的执行来分析了HotSpot的算法实现过程中还要经过的要求
虚拟机算法.png图分析过程如下:
可达性分析算法中从GC Roots节点寻找引用链,但是在一个程序中若是逐个检查引用,会消耗很多时间,并且可达性分析算法对时间非常敏感,要求在分析过程中保持时间的一致性,就像时间被停止一样,不可以出现这边在分析引用链,那边的对象引用还在不停的更改现象,因此在GC过程中必须停止Java所有的执行线程。
为了保证执行效率,并不要求可达性分析算法分析时将所有的引用全部分析完毕,而是直接通过一个叫“OopMap”的数据结构保存对象的引用,这样HotSpot就可以快速而准确的完成 GC Roots 枚举。但是整个系统中的引用那么多,不可能将所有的指令都保存到 OopMap 中,不然会造成GC空间成本的上升。其实HotSpot会在某些特定的地方才会使用OopMap记录信息。
究竟是哪些特定的地方跟程序的状态有关。比如程序正常执行时就会进入到一个叫“安全点”的特定地方进行保存引用信息的操作,反之,要是程序处于被休眠或者被锁的状态,就会进入安全区域来进行保存操作。
安全点(Safe Point)的数量要适当,选取标准为:是否具有让程序长时间执行的特征 为标准进行选定。选取好安全点后,要如何在GC发生时促使所有线程(不包括JNI调用的线程)都进入到安全点呢?这里有两种方法
①抢先式中断(PreeMptive Suspension): 不需要所有线程主动去配合,而是直接将所有线程中断,若发现中断时该线程不在安全点上,那么就会恢复该线程让其跑到安全点上再中断。
②主动式中断(Voluntary Suspension):当进行GC操作时,不直接对线程进行中断,而是给线程一个标志,各线程会自动的查询这个标志是否为true,若为true,那么就会自己中断挂起。(查询标志的地方与安全点重合)
现在的虚拟机基本是采用第二种方式:主动式中断。
安全区域(Safe Region)是指再一段代码片段中,引用关系不会再发生变化,进行GC操作时线程在该区域中的任意位置都是安全的,安全区是升级版的安全点。进入安全区域的线程会有一个标志表明自己已进入安全区域,当发生GC时虚拟机不会管理这些线程。而当这些线程要离开安全区域时,它们就要检查外部的GC操作是否已经完成,若GC已经完成,那么线程会继续执行,若GC没有完成,那么线程就必须在安全区域等待GC完成才能离开。
网友评论