【G1】三色标记与STAB - shenjy24/jackal-gc GitHub Wiki

为什么要用三色标记?

异步执行,传统的基于标记清除法,在GC标记时必须STW,不能异步执行GC操作,而STW对追求实时性的系统来说是不可接收的,三色标记法就是实现了异步操作,能在线程执行的过程中实现并发标记,从而极大地减少了STW时间。

三色标记算法

把对象分成三种颜色;

  1. 黑色:自身和成员变量均标记完成

  2. 灰色:自己完成标记,成员变量没有完成标记

  3. 白色:均未发生标记

最开始所有对象都是白色,然后将自己完标记,但是成员变量没有完成标记的对象设置为灰色,随后将灰色对象的成员变量完成标记,变成黑色。当没有灰色对象的时候就把白色对象回收掉。

(1)漏标问题

并发标记过程中,指向白色对象的所有灰色对象没有再指向它,并且此时黑色对象指向它(黑色指向白色且指向白色的灰色没了)。此时出现漏标,这个白色对象不是垃圾,却会被当成垃圾被回收

(2)解决办法:

从产生漏标的条件出发

  1. 增量更新(IU):跟踪黑色对象指向白色对象的增加,也就是把黑色对象重新标记为灰色(CMS使用的办法)

  2. 原始快照(STAB):跟踪灰色对象指向白色对象的消失,也就是灰色对象指向白色对象引用消失时,把这个引用保存下来,下次扫描还能接着扫描到(将这个引用推到堆栈中),保证白色对象还能被扫描到(GC里面有个栈,这个栈里面全是灰色对象指向白色对象的引用)

为什么G1使用STAB而不使用IU?

灰色->白色引用消失的时候,引用会被push到satb_mark_queue队列中,下次扫描的时候拿到这个引用,找到对应的白色对象,查看它所在的region的RSet,看有无对象指向它,而不需要扫描整个堆就能查找到指向白色对象的引用,效率比较高,注意,是SATB配合RSet效率比较高,不然光是SATB效率高的话,CMS为什么不用SATB而使用IU。

参考资料

G1和三色标记