在了解JVM三色标记算法前请先了解 JVM 垃圾回收算法JVM垃圾收集器,而为什么要将它单独拿出来讲,是因为面试中可能单独问到JVM三色标记法。

概念

JVM三色标记法

JVM三色标记算法是JVM垃圾回收标记的一种算法,它针对的是cms和G1垃圾收集器。

JVM三色标记算法有三种颜色

  • 白色: 在初始状态时,对象尚未被垃圾收集器访问;在结束状态时如果为白色,表示该对象不可达即需要回收。
  • 灰色: 在初始标记的时候将GCRoots关联的对象标记为灰色。
  • 黑色: 在并发标记时,灰色下所有可达对象标记为黑色。

在上面的图示中,

  1. 初始状态都是白色的
  2. 初始标记阶段只将跟GCRoots关联对象A标记为灰色,所以速度很快。
  3. 并发标记阶段灰色下可达对象BC包括A自己标记为黑色,即黑色是安全存活的对象,不会被回收。

对象漏标

在并发标记过程中,标记和用户程序是同时进行的,如果此时,黑色对象(安全存活对象)引用了不可达的对象,则会出现对象漏标,如图所示:

JVM三色标记算法漏标

在上面的例子中,由于并发标记,用户线程干预了对象C,让对象c引用了对象D,造成了对象DE的漏标。

即此时我们不再需要回收对象D,E,但是它们没有被标注为黑色,出现了漏标。

这就是为什么在并发标记后还需要重新标记或者最终标记

解决对象漏标

CMS垃圾收集器解决漏标

CMS使用了增量更新的方法:

还是从上面的例子说明,当未被标记的对象D出现引用的时候,如果引用它的对象C是黑色的则把它标记为灰色,那么在重新标记阶段的时候则会修正对象C,D,E对象,并将它们标记为黑色。

G1垃圾收集器解决漏标

G1使用的是SATB (snapshot at the beginning)算法

  1. 在初始标记的时候生成一个快照图,标记存活对象
  2. 在并发标记的时候出现了引用修改会把这些引用的原始值捕获下来,上面例子中记录C对象,记录在log buffer中,
  3. 在再次标记阶段配合Rset,去扫描哪些Region引用到当前的白色对象,若没有引用到当前对象,则回收