Java虚拟机实现垃圾收集算法时,必须对算法的执行效率有严格的考量,才能保证虚拟机高效运行。
一、根节点枚举
所有收集器在根节点枚举这一步骤时都是必须暂停用户线程的。让执行子系统看起来就像被冻结在某个时间点上,不会出现分析过程中,根节点集合的对象引用关系还在不断变化的情况。
而跟节点枚举这个操作是非常耗时的,必须做到高效。
HotSpot 使用一组称为OopMap的数据结构作为优化。一旦类加载动作完成,HotSpot就会把对象内哪些偏移量上是哪些类型的数据计算出来,在即时编译过程中,也会在特定的位置记录下栈里和寄存器里哪些位置是引用。这样收集器在扫描时就可以直接得知这些信息。
二、安全点
在OopMap的协助下,HotSpot可以快速准确地完成GC Roots枚举,如果为每一条指令都生成对应的OopMap,那将会需要大量的额外存储空间,这样垃圾收集伴随而来的空间成本就会高昂到无法忍受。
解决方案之一是在“特定的位置”记录信息,生成OopMap,这些记录位置点被称为安全点(Safepoint)。
对于安全点,如何在垃圾收集发生时让所有线程都跑到最近的安全点,然后停顿下来,有两种方式:
2.1 抢先式中断 (Preemptive Suspension)
抢先式中断不需要线程的执行代码主动去配合。
在垃圾收集发生时,系统首先把所有用户线程全部中断,如果发现有用户线程中断的地方不在安全点上,就恢复这条线程执行,让它一会再重新中断,直到跑