垃圾采集器和内存分配策略-HotSpot算法实现
优采云 发布时间: 2020-08-07 03:05以前,我们介绍了如何判断对象是否还活着并实现相关的垃圾采集算法. 在此基础上,我们将讨论在HotSpot中实现这些算法时必须满足的要求,以确保算法的有效执行.
首先,让我们看一下图片: 该图片分析了在执行HotSpot算法和执行可达性分析算法时必须满足的要求
虚拟机algorithm.png
图像分析过程如下:
可达性分析算法从GC Roots节点搜索参考链,但是如果您在程序中一个接一个地检查参考,则会消耗大量时间,并且可达性分析算法对时间非常敏感,在分析过程中需要时间时间的一致性就像时间已经停止一样. 无法在此处分析引用链,并且那里的对象引用仍在变化. 因此,必须在GC进程中停止所有Java执行线程.
为了确保执行效率,在分析可达性分析算法时并不需要分析所有参考. 而是直接通过称为“ OopMap”的数据结构保存对象的引用,以便HotSpot可以快速而准确地完成GC根枚举. 但是,由于整个系统中的引用过多,因此无法将所有指令保存在OopMap中,否则会增加GC空间的成本. 实际上,HotSpot只会使用OopMap在某些特定位置记录信息.
哪些特定点与程序状态有关. 例如,当程序正常执行时,它将进入一个称为“安全点”的特定位置以保存参考信息. 相反,如果程序处于休眠或锁定状态,它将进入一个安全区域进行保存.
安全点的数量应适当. 选择标准是: 是否具有允许程序长时间执行的特征. 选择安全点之后,如何在发生GC时使所有线程(不包括JNI调用的线程)进入安全点?这里有两种方法
①抢先中断(PreeMptive Suspension): 不需要所有线程积极配合,而是直接中断所有线程. 如果在中断时发现线程不在安全点,则将还原该线程并使其安全运行. 单击然后中断.
②自愿暂停: 执行GC操作时,线程不会直接中断,而是会给该线程一个标志. 每个线程将自动检查该标志是否为true. 如果为真,则自行挂起. (查询标志的位置与安全点重合)
当前的虚拟机基本上使用第二种方法: 主动中断.
安全区域意味着在另一段代码中,引用关系将不再更改. 执行GC操作时,该线程在该区域中的任何位置都是安全的. 安全区域是安全点的升级版本. 进入安全区域的线程将带有一个标志,表明它们已进入安全区域,并且在发生GC时虚拟机将不会管理这些线程. 当这些线程要离开安全区域时,它们必须检查外部GC操作是否已完成. 如果GC已完成,则线程将继续执行. 如果GC未完成,则线程必须在安全区域中等待,以等待GC完成后再离开.