cms三次标记浮动垃圾是如何产生的

cms收集器为什么会产生浮动垃圾?

cms垃圾收集器采用三次标记,一次清除来对垃圾进行标记,清除的,第一次标记是stop-the-world的,用来标记处gcroot可达的对象。第二次标记是并发标记,用来根据root对象进行标记出可关联的对象。
没有stop-world,第三次标记,重新标记,用来标记并发标记产生的变动对象。

问题: 为什么只有第二次标记不需要stop-world?
要知道堆区的对象很多,老年代最多,如果对老年代所有的对象标记时进行stop-world,那么停顿时间就太长了,用户难以忍受,而我们只需要标记处root节点就可以了,所以第一次标记时,stop-world就是为了标记出root节点,第二次标记不需要stop-world,只需要对这些root节点往下继续扫描。因此第二次标记不需要stop-world就是为了减少stop-world的时间。
问题:为什么第二次标记会产生浮动垃圾?
因为第二次标记是和用户线程并行的,因此用户线程可能会随时对一个标记为可达的对象进行修改成不可达,例如a引用了b,此时b被扫描为可达,但是用户线程之后对a.b=null,这个时候b依然作为可达的,因此就成了浮动垃圾。

问题:除了浮动垃圾外,第二次标记还有什么问题:?
对象消失的问题,因为用户线程和gc线程并行,不仅仅用户会把之前标记为可达的对象改为没有引用外,还会对一个理论上不可达的对象变的可达,例如a.b=c c.d=e, 如果gc只扫描到了b,然后用户线程突然把b.c=null,c.d = a.d ;这个时候 c已经不可达了,虽然d被a.d引用,但是由于gc认为a已经被扫描过了,因此d就是一个不可达的对象,会被清理掉。

标记的底层原理:
三原色标记,黑色表示该节点所有的引用都被扫描了,灰色表示部分扫描过了,白色表示没有被引用。
所以第二次扫描的时候,原来是非白色的,被用户去掉了引用,这个时候,该多余的黑色就成了浮动垃圾,本次无法被清理,只能等下次清理。
一些黑色的节点,被用户线程意外的加入了一个白色节点,这个时候,该白色不会被扫描,就会被清除,导致对象消失。

问题:如果防治对象消失的?
jvm在执行引用赋值的时候实际上也运用了类似aop的技术原理,即在赋值前后进行around通知,来进行修改,对于cms收集器,可以对黑色节点加入白色之后进行修改源节点色颜色,使黑色变成灰色。原理是通过一个写屏障,在对引用赋值时,加入屏障进行aop执行。
对于g1收集器,则是完全对灰色节点进行重新扫描。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值