在了解JVM三色标记算法前请先了解 JVM 垃圾回收算法和JVM垃圾收集器,而为什么要将它单独拿出来讲,是因为面试中可能单独问到JVM三色标记法。
概念
JVM三色标记算法是JVM垃圾回收标记的一种算法,它针对的是cms和G1垃圾收集器。
JVM三色标记算法有三种颜色
- 白色: 在初始状态时,对象尚未被垃圾收集器访问;在结束状态时如果为白色,表示该对象不可达即需要回收。
- 灰色: 在初始标记的时候将GCRoots关联的对象标记为灰色。
- 黑色: 在并发标记时,灰色下所有可达对象标记为黑色。
在上面的图示中,
- 初始状态都是白色的
- 初始标记阶段只将跟GCRoots关联对象A标记为灰色,所以速度很快。
- 并发标记阶段灰色下可达对象BC包括A自己标记为黑色,即黑色是安全存活的对象,不会被回收。
对象漏标
在并发标记过程中,标记和用户程序是同时进行的,如果此时,黑色对象(安全存活对象)引用了不可达的对象,则会出现对象漏标,如图所示:
在上面的例子中,由于并发标记,用户线程干预了对象C,让对象c引用了对象D,造成了对象DE的漏标。
即此时我们不再需要回收对象D,E,但是它们没有被标注为黑色,出现了漏标。
这就是为什么在并发标记后还需要重新标记或者最终标记。
解决对象漏标
CMS垃圾收集器解决漏标
CMS使用了增量更新的方法:
还是从上面的例子说明,当未被标记的对象D出现引用的时候,如果引用它的对象C是黑色的则把它标记为灰色,那么在重新标记阶段的时候则会修正对象C,D,E对象,并将它们标记为黑色。
G1垃圾收集器解决漏标
G1使用的是SATB (snapshot at the beginning)算法
- 在初始标记的时候生成一个快照图,标记存活对象
- 在并发标记的时候出现了引用修改会把这些引用的原始值捕获下来,上面例子中记录C对象,记录在log buffer中,
- 在再次标记阶段配合Rset,去扫描哪些Region引用到当前的白色对象,若没有引用到当前对象,则回收