根节点枚举
在可达性算法当中是通过GC ROOT的引用找到存活对象的方式,在现代的收集器基本可以做到和用户线程一起并发执行的程度,但是根节点枚举要保证某个时间点的“快照”,这也意味着根节点枚举需要暂停用户线程。
一套完整的“GC Roots”也必须考虑分代回收和局部回收的问题。例如 Partial GC 针对堆中某块区域的发起垃圾回收时,也必须考虑此内存区域内的对象是否可能被其他区域引用? 所以此时也必须将这些关联区域的对象一起加入到“GC Roots”集合里,才能保证可达性分析的正确性。
OopMap 数据结构
枚举出整个“GC Roots”是非常麻烦的
- 运行时数据本身就是动态的。
- Java应用越来越大。
JVM 如何解决呢?
首先在进行根节点选举时,必须暂停全部的用户线程,我们把这个过程称为“Stop The Word”(下面简称STW)(注:但必须要说明,STW不一定是全局的,也可以是局部的,这和安全点的类型有关。此时说的必须暂停全部用户线程只是因为GC时必须使全部线程进入安全点(gc safe point))。
在HotSpot的解决方案中,是使用一组称为OopMap的数据结构来存放这些对象的引用(OopMap在类加载动作完成时生成)。也就是说当用户线程暂停下来之后,其实并不需要一个不漏的检查完所有的执行上下文和全局的引用位置。而是直接通过OopMap来获取栈上或寄存器里哪里有GC管理的指针(引用指针)。
这种结构会存在哪些问题?
这里可以看到,如果每一次对象的读取变化,都需要往OopMap里面存储内容,会导致OopMap的内容不断臃肿扩大,垃圾收集器的扫描成本会变得非常的昂贵。
为了应对这一类问题,HotSpot引入了“安全点这一机制进行处理”。
网友评论