JVM垃圾回收——三色标记

目录

一、CMS和G1垃圾回收过程

二、什么是三色标记

三、标记过程

四、并发标记产生的问题

五、写屏障

六、 为什么CMS采用增量更新而G1使用原始快照?有什么区别?


一、CMS和G1垃圾回收过程

CMS:开始标记(会STW)——>并发标记(与用户线程并行)——>重新标记(会STW)——>并发清除

G1:   开始标记(会STW)——>并发标记(与用户线程并行)——>最终标记(会STW)——>筛选回收

二、什么是三色标记

1、白色:还没有被垃圾回收器标记的对象

2、灰色:已经被垃圾回收器标记的对象,但至少还有一个直接引用没有被标记

3、黑色:所有引用都已经被垃圾回收器标记的对象

三、标记过程

1、最开始除root根对象是黑色外,所有对象都是白色的

2、将根直接引用的对象标记为灰色

3、将灰色对象能直接引用到的白色对象标记为灰色,将其本身标记为黑色

4、将没有再被引用的灰色对象标记为黑色

5、重复上面过程直到没有灰色

如上图所示,标记之后依然是白色的对象D就是需要被回收的垃圾对象

四、并发标记产生的问题

由于并发标记是与用户线程并行的,所以在并发标记的过程中对象的引用是可能发生变化的,所以可能会产生多标和漏标。并且重新标记为了减少STW的时间不会再标记黑色对象,而是扫描灰色对象的直接引用

多标:会导致产生浮动垃圾,需要在下一次判断引用再回收,无大碍

漏标:会导致不应该被回收的对象被回收,问题严重

如上图:在并发标记的过程中,同时产生这两种情况时就会发生回收错误问题:A和C断开了引用,A又引用了D。

对于对象C:应该回收的对象现在是黑色,留了下来

对于对象D:被引用了但还是白色,由于重新标记时不会再扫描黑色对象,这样会导致对象D被当作垃圾而回收,产生严重bug

五、写屏障

JVM通过写屏障来解决并发标记过程中产生的漏标问题。就是在写操作的前后做一些事情,类似AOP原理

建立引用和删除引用对应代码其实就是一个赋值的写操作:

public static void main(String[] args) {
    A a = new A();
    A b = null;
    b = a;//建立引用
    b = null;//删除引用
}

上面说过:同时发生A和C断开了引用,A又引用了D时会有回收错误问题,所以我们只需要破坏其中一种情况即可。

CMS使用增量更新方式:如果要gc的对象又被重新引用了,在建立引用之后把新对象记录下来,然后把引用了新对象的节点变成灰色

G1原始快照方式:当删除引用关系时,在删除引用关系之前做快照,将发生变化的引用关系记录下来,对比变化后重新标记引用链,并把要删除的对象标记为黑色。如果最终这次真的删除了引用关系且没有新的引用,那就做为浮动垃圾下次再标记回收也可以,但这次不能误删

六、 为什么CMS采用增量更新而G1使用原始快照?有什么区别?

1、增量更新是把引用了新对象的对象标记为灰色,重新标记时会再次扫描,过程慢,但不会产生浮动垃圾,cms是一整块old区,慢点也没关系
2、原始快照把要删除的对象标记为黑色,重新标记时不会再扫描黑色,过程快,但是代价是会产生浮动垃圾。G1是将整个堆划分为多个小区域,需要快速清理垃圾

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值