当前位置: 首页 > 图灵资讯 > 技术篇> 三色标记算法

三色标记算法

来源:图灵教育
时间:2023-06-17 13:53:26

  前言由于引用奇数法会导致循环引用问题,JVM默认使用可达性分析算法来判断对象是否存活。标记-清除 标记-复制 和 标记-整理 在此基础上,算法是新一代/老年人的垃圾收集算法 JVM采用不同的垃圾回收算法,提高整体分配和回收效率 CMS、G1垃圾回收器使用的垃圾回收算法是 三色标记算法 通过一系列的“可达性分析算法”GC ROOTS“搜索对象作为根节点, 为了保证根节点在枚举过程中对象引用关系不会改变,STW

  三色标记算法三色标记算法的出现是为了有效地标记可回收的内存块,以减少或解决用户线程的停顿算法思想

  根据“是否访问”,将经历过的对象标记为以下三种颜色 白色:未被访问,可达性分析算法刚刚开始,所有对象都是白色的。如果分析结束,仍然是白色的,认为是不可达的 黑色:被访问,所有参考都被访问,其他参考对象可以直接指向黑色对象。黑色对象不能直接指向白色对象 灰色:对象被访问,其引用尚未扫描 标记过程

  1.初始阶段为白色2。所有GC ROOTS直接引用标记为灰色3。灰色集合中的对象没有子引用,标记为黑色,子引用,将所有子引用对象放入灰色集合,当前对象放入黑色集合4。重复步骤3,直到所有灰色对象都变成黑色对象。此时,白色对象是垃圾对象,即不能到达对象5。回收白色对象可作为GC ROOTS的对象 在虚拟机栈(栈帧中本地变量表)中引用的对象 该方法用于引用中等静态属性的对象 方法区常量引用的对象 在Native方法中引用的对象 误标情况 同时标记线程和用户线程 用户线程在标记过程中修改了引用关系

  将回收对象标记为生存,产生浮动垃圾 GC已被标记为黑色对象,并发过程中引用链断开,导致该对象的垃圾回收无法处理,只能在下一次垃圾回收中处理。生存垃圾被标记为死亡

  产生误标的条件 将一个或多个黑色对象插入到白色对象的参考中 赋值器删除了从灰色对象到白色对象的所有直接引用或间件引用 误标解决方案增量更新 如果建立黑色对象指向白色对象的引用关系,记录下来。并发扫描结束后,以记录的黑色对象为根再次扫描 原始快照(STAB)

  当灰色对象想要删除指向白色对象的引用关系时,记录要删除的引用关系,即建立快照并发扫描结束,并根据快照重新扫描灰色对象浮动垃圾漏标和多标多标多标产生浮动垃圾

  如下图所示,BCDE将成为浮动垃圾。下次清理垃圾时,将回收另一种情况。在标记过程中产生的新对象默认标记为黑色,但在标记过程中可能成为垃圾,这也是浮动垃圾的一部分

三色标记算法_可达性

漏标-读写屏障漏标

三色标记算法_可达性_02

写屏障+STAB(原快照)

  所谓写屏障,其本质是在赋值变量前后增加一些处理 void oop_field_store(oop* field, oop new_value) { pre_write_barrier(field); // 写屏障-写前操作 *field = new_value; post_write_barrier(field, value); // 写屏障-写后操作}

  写屏障有助于建立原始快照,即记录引用关系改变前的情况,即GC ROOTS 开始后,快照的对象图已经确定了扫描时按照对象图进行扫描,以避免标记遗漏写屏障+增量更新

  如上图所示,当A对象的引用关系发生变化时,记录新的成员变量C插入新的引用,记录新的引用对象,等待遍历,即增量更新读屏障

  当B读取C时,记录C。此时,C为白色对象A和C建立引用关系的前提是C被记录并从记录中获取C对象。由于记录中存在C对象,C对象不会被错误回收