ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 枚举根节点、安全点、安全区域 在根可达性分析算法中,从GC Roots集合中找引用链是虚拟机高效实现的第一个例子。 ### 问题一:为什么要枚举根节点?怎么高效实现? ![](https://img.kancloud.cn/50/07/500702775b23ca7437a7fca64518c486_1538x820.png) 虽然GC Roots的节点主要在全局性的引用(例如常量或者类静态变量)与执行上下文(例如栈帧中的局部变量表),但是查找起来并发容易的事。 ### 问题一解决之道:使用根可达分析算法判断垃圾,所以需要枚举根节点。通过在安全点生成并维护OopMap来高效计算GC Roots集合。 为了解决某个时刻GC Roots集合的定位问题,在HotSpot中,有个数据结构(映射表)称为**OopMap**。一旦类加载动作完成的时候,HotSpot就会把对象内什么偏移量上是什么类型的数据计算出来,记录到OopMap。在即时编译过程中,也会在**特定的位置**生成 OopMap,记录下栈上和寄存器里哪些位置是引用。这样在垃圾收集器在**枚举根节点**时,就可以通过扫描OopMap中的对象快速得到当时的GC Roots集合。 (每个安全点都会生成对应的OopMap) ### 问题二:为什么需要安全点?安全点在哪些位置? 进行垃圾回收的过程中,会涉及对象的移动。为了保证对象引用更新的正确性,必须暂停所有的用户线程(会发生STW)。线程并不是在任意位置都能中断挂起的,只有在特定的位置才行。 这些特定的位置: * 方法调用 * 循环跳转(非 counted 循环,固定循环次数) * 异常跳转 称之为**安全点**(每个安全点都会生成对应的OopMap),垃圾收集时,需要用户线程到达安全点停下来后才开始执行。 在HotSpot中,采用主动式中断的思想让做垃圾收集时让所有用户现在都跑到最近安全点停顿下来。 是在安全点和分配对象时设置一个中断标志,各线程执行时会不停轮询这个标志,一旦发现为真时就在最近安全点主动挂起。 ### 问题三:为什么需要安全区域? 安全点的设计几乎完美解决如何停顿用户线程,让虚拟机进入垃圾回收状态。可如果用户线程处于Sleep或者Blocked状态时,线程是无法响应中断请求的,虚拟机也不可能等待线程被激活后走到安全点挂起自己,这个时候就需要安全区域来解决了。 **安全区域**是指能够确定在某一段代码之中,引用关系不会发生变化,因此这个区域内任意地方开始垃圾回收都是安全的。(安全区域是扩展了的安全点)