JVM中的三色标记法

183 阅读2分钟

不同颜色的含义

  • 白色:表示对象尚未被垃圾收集器访问过。最开始全为白色;最终为白色代表不可达,需要回收

  • 黑色:表示对象已经被垃圾收集器访问过;且这个对象的所有引用都已经扫描过,不需要回收;

  • 灰色:表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用还没有被扫描过。

** 最终回收白色节点,只剩下黑色节点。 **

过程

  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:用来记录之前的引用关系,后续的标记按该引用关系走。针对步骤二

写屏障 + 增量更新:记录新的引用关系。针对步骤三