三色标记算法详解

把Gcroots可达性分析遍历对象过程中遇到的对象, 按照“是否访问过”这个条件标记成以下三种颜色:

  • 黑色:被垃圾收集器扫描完毕,对象内的所有引用都被扫描完成,之后不会在被扫描
  • 灰色 :被垃圾收集器访问过,但还至少有一个引用没有被扫描
  • 白色:尚未被垃圾收集器访问过。
    起初所有对象都是白色的,注意,黑色对象永远不可能直接指向白色对象,只能指向灰色对象或者是黑色对象

在并发标记的过程中,因为标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。

多标 浮动垃圾

在CMS和G1这种垃圾收集器中并发标记的过程中由于用户线程也在跑,那么可能刚才标记为非垃圾对象就变为垃圾对象了,那么这些对象就是多标。

漏标

在并发标记的过程中,一个Gcroot内成员变量所引用到的B对象他的成员变量又引用别的D对象,B对象的调用D对象的成员变量在还没有被扫描到之前被清空了,那么这个时候Gcroot对象(已经变为黑色)再引用上这个D对象,那么这个对象就不会被扫描到,这个非垃圾对象会被当做垃圾对象误删除。

漏标会导致被引用的对象被当成垃圾误删除,这是严重bug,必须解决,有两种解决方案:

增量更新:

增量更新就是当黑色对象插入新的指向白色对象的引用关系时, 就将这个新插入的引用记录下来, 等并发扫描结束之后, 再将这些记录过的引用关系中的黑色对象为根, 重新扫描一次。可以简单理解为 黑色对象一旦新插入了指向白色对象的引用之后, 它就变回灰色对象了。在重新标记时会被从新扫描

原始快照:

就是当灰色对象要删除指向白色对象的引用关系时, 就将这个要删除的引用记录下来, 在并发扫描结束之后,再将这些记录过的引用关系中的灰色对象为根, 重新扫描一次,这样就能扫描到白色的对象,将白色对象直接标记为黑色,可能会被当作浮动垃圾。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容