三色标记(可达性分析算法)及一些思考

三色标记算法及一些思考

  • 三色标记算法
  • 并发下导致的问题
  • 解决方式

最近,在阅读《深入理解Java虚拟机》一书关于可达性分析内容的描述后,有些感悟,故写下此文章。

首先,我们假设根节点已经枚举完毕,并以该根节点为起点对Java对象进行可达性分析,

三色标记算法

在可达性分析的过程中,先约定好三种颜色的含义,按照“是否访问过”进行划分:

  • 白色:对象未被垃圾回收器访问过。在垃圾回收结束之后,对象仍然为白色,即表示不可达。
  • 黑色:对象及其所有引用都已被扫描过,是安全可存活的。
  • 如果由其它对象的引用指向黑色对象无需重新扫描。
  • 黑色对象不可直接指向白色对象。
  • 灰色:对象已被访问过,但这个对象上至少存在一个引用还没有被扫描。

那么假设单线程执行(此时用户线程都被挂起),执行顺序如图所示,这个过程是没啥问题的。
三色标记(可达性分析算法)及一些思考_第1张图片
(该图来源于《深入理解Java虚拟机》P88)

并发下导致的问题

如果用户线程和垃圾回收的线程并发执行,那么可能会有如下的执行顺序:
三色标记(可达性分析算法)及一些思考_第2张图片

阅读这部分内容的时候,一直在纠结一个点,前文提到黑色对象不可直接指向白色对象的,这里又说用户线程将白色对象与黑色对象建立了引用关系,两者之间是否矛盾?后边想了想,前者说的【黑色对象不可直接指向白色对象】应该是指垃圾回收线程正常执行的情况下,无用户线程并发修改引用的场景。

即用户线程和垃圾回收线程并发执行时会带来两种可能性:

  • 原本应该消失的对象在可达性分析之后存活了。(浮动垃圾,可容忍,大不了下次清理)
  • 原本应该存活的对象在可达性分析之后消失了。(0容忍)

对此,书中也给出了对象消失的先决条件(两者需要同时成立):

  • 赋值器插入了一条或多条从黑色对象到白色对象的新引用;
  • 赋值器删除了全部从灰色对象到该白色对象的直接或间接引用

解决方式

知道对象消失的先决条件,那么解决方式只要破坏其中一条即可:

  • 增量更新(CMS)
    • 当赋值器插入了一条或多条从黑色对象到白色对象的新引用时,将该引用记录下来,在并发可达性分析结束之后重新扫描。
  • 原始快照(G1)
    • 按照一开始扫描的对象图进行搜索,如果在这个过程中,赋值器删除了全部从灰色对象到该白色对象的直接或间接引用,将该引用记录下来,在并发可达性分析

这里阅读时也有个疑问,如果采用原始快照的方式,在可达性分析的过程中,用户线程新增了一个对象,并将黑色对象指向白色对象,这个时候如何处理?这里就要关注一个点了,【原始快照】即一开始扫描的对象图,在可达性分析的过程中,新增加的对象理所当然不在该对象图中。

你可能感兴趣的:(JVM深入学习,可达性分析,三色标记,Java对象存活判断)