三色标记清除法

1、三色标记算法的概述

在我们进行垃圾扫描时,学习过两种算法:引用计数和可达性分析,在Java中我们主要使用的是可达性分析。

可达性算法的三个基础算法为:标记-清除标记-复制标记-清除。如果是在STW的情况下,那么哪种算法都不会出错,无非是效率罢了。但是随着计算器硬件的发展,与之对应的计算机软件技术及思想也在不断进步。如在多并发的基础之上,减少STW的时间,完成对垃圾的清除,边清除边标记,这就引出了三色标记算法

三色指的是:黑色灰色白色

  • 黑色: 表示对象以及被垃圾收集器访问过,且这个对象的引用都已经扫描过。黑色的对象代表以及扫描过,他是安全存活的,如果有其他对象引用指向了黑色对象,无需重新扫描一遍。黑色对象不可能直接(不经过灰色对象)指向某个白色对象。
  • 灰色: 表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用还没有被扫描到
  • 白色: 表示对象尚未被垃圾收集器访问过。显然在可达性分析刚刚开始的阶段,所有的对象都是白色,如在分析结束的阶段,仍然是白色的对象,即代表不可达。

2、三色标记的过程

在这里插入图片描述

假设现在有白、黑、灰三个集合(表示当前对象的颜色)

  1. 刚开始,所有对象都在白色集合中
  2. 将GC Roots直接引用的对象挪到灰色集合中
  3. 灰色集合中获取对象:
    • 将本对象的引用到的对象放入灰色集合中
    • 将本对象放入黑色集合中
  4. 重复步骤3,直到灰色集合为空结束
  5. 结束后,仍在白色集合的对象即为GC Roots不可达,可以进行回收。

注:如果标记结束后对象仍为白色,意味着已经“找不到”该对象在哪了,不可能会再被重新引用。例如没有任何引用指向H了,它是白色,也不可能再有对象引用指向它了。

3、存在问题

用户线程和垃圾回收线程都是线程,自然就有停顿的时间,如果垃圾回收线程的时间片到了,而用户线程做了其他的操作,这就导致了会出现错标和漏标的问题。

3.1 错标

标记过不是垃圾的,变成了垃圾(也叫浮动垃圾),如图:

在这里插入图片描述

垃圾回收线程刚刚将D扫完,将D标为黑色,此时垃圾回收线程时间到了,垃圾回收线程暂停。用户线程将D指向E的关系改为,D.E=null从我们的角度来看,E已经是垃圾了,但是E仍然是灰色,扫描完E后,E会变为黑色,但是这并不影响这个程序的执行,在下一次垃圾回收的过程中,垃圾回收线程就会将E回收掉。

3.2 漏标

这个问题是比较严重的,如下图所示

在这里插入图片描述

垃圾回收线程将D标记为黑色,表示D已经扫描完成。此时去扫描他的引用对象E,但是此时垃圾回收线程暂停,用户线程执行了这样一个操作:E.G = null, D.G = G。然后垃圾回收线程回来继续扫描E,**此时在E看来,G就是一个不可达的对象。但是D又引用着G,可是D是黑色,不会在回去重新扫一遍,垃圾回收结束,G的颜色为白色,被清除掉,D去调用G对象,出现空指针异常。**这真的是一件非常恐怖的事情。

4、解决错杀问题

上边描述过了,错杀的情况只有在 下边两个条件同时发生,才会发生:

  1. 黑色对象指向了白色对象
  2. 本来指向这个白色对象的灰色对象断开了对他的连接

在这里插入图片描述

4.1 CMS:写屏障+增量更新(Incremental Update)

在CMS中,如果出现这样的情况:黑色对象指向了白色对象(D.G = G),在执行操作之前,使用钩子函数(写屏障,类似于AOP),将对象D从黑色变为灰色,这样就使得可以扫到D了。

那么对应灰色集合而言,就等于是一个增量更新。

4.2 G1:写屏障+原始快照(STAB)

在G1中,如此出现这样的情况:灰色对象断开了对白色对象的引用(E.G = null),在执行操作之前,使用钩子函数(写屏障,类似于AOP),将这个要删除的引用记录下来,在并发扫描结束后,再扫描一遍。

这种做法的思路是:尝试保留开始时的对象图,即原始快照(Snapshot At The Beginning,SATB),当某个时刻 的GC Roots确定后,当时的对象图就已经确定了。

比如 当时 D是引用着G的,那后续的标记也应该是按照这个时刻的对象图走(D引用着G)。如果期间发生变化,则可以记录起来,保证标记依然按照原本的视图来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值