jvm 三色标记法

三色标记法

这个算法就是把 GC 中的对象划分成三种情况:

白色:还没有搜索过的对象(白色对象会被当成垃圾对象)
灰色:正在搜索的对象
黑色:搜索完成的对象(不会当成垃圾对象,不会被GC)
上面说的这个问题就是可以用下图来表示:

这里写图片描述

这个图的意思就是:假设有 A -> B -> C, A 是 GC Roots 关联的对象,那么首先会把 GC Roots 标记,也就是 A 标记成灰色(证明现在正在搜索 A 相关的),然后搜索 A 的引用,也就是 B,那么搜索了 B,把 B 变成了灰色,那么 A 就搜索完成了。(此时注意,现在是不管 C 的,因为 C 不是 A 的引用,现在只管 A 的引用是什么)。此时把 A 相关的搜索完了,那么 A 就变成了黑色,证明 A 已经 ok 了。

(Ps:浮动垃圾就是说,此时 A 又不用了,那么 A 是没办法回收的,因为 A 已经标记了)

此时准备要搜索 B 了。

刚好,此时,用户线程要执行了,用户线程把原来 A -> B -> C 的引用改成了 A -> C,同时 B 不再引用C。

然后又到 GC 线程执行了。

GC 线程发现 B 没有引用的对象了(因为用户线程已经把 B -> C 去掉了),那么 B 就相当于搜索完成了,变成黑色了。

最后,C 怎么办,C还是白色的呢,白色的是不会搜索,当做垃圾处理的。

解决办法

此时的解决办法就是有一个叫做写入屏障的东西。就是说,如果A已经被标记了(已经是黑色的了),那么用户线程改动 A->C的时候,会把 C 变成灰色,这样,以后就可以搜索 C了。

例如:

write_barrier(obj,field,newobj){
    if(newobj.mark == FALSE){
        newobj.mark = TRUE
        push(newobj,$mark_stack)
    }
    *field = newobj
}

这里的意思就是改的时候会 push(newobj,$mark_stack),

那么,通过这样子的一个方式,就能解决这个问题:GC 线程和 用户线程并发的时候,用户线程把失效的对象又至为有效,这个时候怎么处理。

cms 的解决方案 增量更新 Incremental Update

并发线程执行时 a 变为黑色

线程2 在线程1标记完A时 A指向c a会变灰

会产生ABA 问题

所以 cms 的remark 阶段 ,必须从头扫描一遍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值