了解虚拟机中的垃圾回收和OopMap数据结构
我们根据可达性分析可知,通过GC Roots节点我们可以判断一个对象是否还被引用。但现在有很多应用仅仅是方法区就有数百兆大小,逐个检查引用,必然消耗过多的时间。就连号称不会发生停顿的CMS收集器,枚举根节点时也必须要停顿。
在HotSpot虚拟机中,一组称为OopMap的数据结构解决了这个问题,在类加载的完成的时候,HotSpot加吧对象内什么偏移量上是什么数据类型的数据就计算出来了,在编译过程中,也会在特定位置记下栈和寄存器中哪些位置是引用,GC在扫描时就可以直接得知这些信息。
什么是安全点?
我们了解到虚拟机中存在垃圾回收机制来保证我们的内存正常连续的使用,那我们也应该想到一些问题。难道垃圾回收什么时间点都能执行吗?答案时候否定的。
在OopMap的帮助下,HotSpot可以快速准确的完成GC Roots枚举,但事实上不可能为每一条指令都创建OopMap,这样会占用大量的空间,因此只在特定位置记录这些信息,这些特定位置就称为安全点(Safepoint)。程序只有到达安全点之后才能执行GC,并不是所有地方都能停下来进行GC。
安全点的选定标准
安全点的选定标准既不能让GC等待时间过长,也不能使GC过于频繁。程序指令的执行时间都是非常短暂的。所以安全点的选定标准为:是否具有让程序长时间执行的特征。 例如:方法调用、循环跳转、异常跳转等具有这些功能的指令会产生安全点。
关于安全点的一些其他问题
如何在GC发生时,让所有线程都跑到最近的安全点停下来。
方案1:抢先中断式中断
这个方案不需要线程执行代码去配合,GC发生后,先全部中断所有线程,发现有没有在安全点上的线程时,让其恢复,跑到最近安全点后再中断。
方案2:主动式中断
这个方案不直接操作线程,而是设置一个标志,让各个线程去主动轮询这个标志,发现中断标记为真时,主动中断,轮询标志的地方和安全点是重合的。