不同颜色的含义
-
白色:表示对象尚未被垃圾收集器访问过。最开始全为白色;最终为白色代表不可达,需要回收
-
黑色:表示对象已经被垃圾收集器访问过;且这个对象的所有引用都已经扫描过,不需要回收;
-
灰色:表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用还没有被扫描过。
** 最终回收白色节点,只剩下黑色节点。 **
过程
1.在 GC 标记开始的时候,所有的对象均为白色;
2.在将所有的 GC Roots 直接引用的对象标记为【灰色集合】;
3.从【灰色集合】中取出对象: 将本对象引用到的其他对象全部挪到 【灰色集合】中; 将本对象挪到【黑色集合】里面
4.重复步骤3,直至【灰色集合】为空时结束。
5.标记结束后,为白色的对象为 GC Roots 不可达,可以进行垃圾回收。
问题:多标
程序执行时,对象变灰后,引用链断开,实际应该为白色但却是黑色。
解决方案:等到下一轮垃圾回收中清除。
问题:漏标
原来:D->E->G;但是现在:D->G,D->E。E 已经没有对 G 的引用了,所以不会将 G 放到灰色集合;尽管因为 D 重新引用了 G,但因为 D 已经是黑色了,不会再重新做遍历处理。
最后G实际应该为黑色,但是为白色被清除了。
漏标的解决方案:读写屏障
读屏障:当读取成员变量时,一律记录下来。针对步骤一
写屏障+SATB:用来记录之前的引用关系,后续的标记按该引用关系走。针对步骤二
写屏障 + 增量更新:记录新的引用关系。针对步骤三