首页IT科技三色标软件(一文弄懂三色标记算法)

三色标软件(一文弄懂三色标记算法)

时间2025-05-03 14:36:47分类IT科技浏览6065
导读:本文已收录至Github,推荐阅读 ? Java随想录...

本文已收录至Github                ,推荐阅读 ? Java随想录

微信公众号:Java随想录

CSDN: 码农BookSea

你愈是少说你的伟大                    ,我将愈想到你的伟大                。——培根

面试官:我们先从JVM基础开始问      ,了解三色标记算法吗?

我:额......不了解                    。

面试官:出去的时候记得把门带上      。

现在Java面试真的已经是越来越卷了            ,很喜欢问底层实现原理            。本篇来聊聊三色标记算法                     ,也是Java面试的常客                     。

三色标记算法可以扯出增量更新和原始快照         ,聊好了会让面试官觉得你这小伙子有点东西         。

三色标记算法

既然叫三色标记算法        ,首先我们要搞明白是哪三色                      ,三色是:黑色            ,白色    ,灰色        。

把遍历对象图过程中遇到的对象                       ,按照是否访问过这个条件标记成以下三种颜色:

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

原书中的图画的很好                     ,一目了然                    。

由于一些垃圾回收器存在垃圾回收线程和用户线程并发的情况(例如CMS的并发阶段)         ,那么三色标记会有2个问题

一种是把原本消亡的对象错误标记为存活        ,这不是好事                      ,但其实是可以容忍的            ,只不过产生了一点逃过本次收集的浮动垃圾而已    ,下次收集清理掉就好                   。 另一种是把原本存活的对象错误标记为已消亡                       ,这就是非常致命的后果了               ,程序肯定会因此发生错误   。

Wilson于1994年在理论上证明了,当且仅当以下两个条件同时满足时                    ,会产生“对象消失                ”的问题                   ,即原本应该是黑色的对象被误标为白色:

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

因此   ,我们要解决并发扫描时的对象消失问题                ,只需破坏这两个条件的任意一个即可      。由此分别产生了两种解决方案:增量更新(Incremental Update)和原始快照(Snapshot At The Beginning                    ,SATB)            。

这2种解决方案各破坏一个条件

增量更新

增量更新要破坏的是第一个条件      ,当黑色对象插入新的指向白色对象的引用关系时            ,就将这个新插入的引用记录下来                     ,等并发扫描结束之后         ,再将这些记录过的引用关系中的黑色对象为根        ,重新扫描一次                     。这可以简化理解为                      ,黑色对象一旦新插入了指向白色对象的引用之后            ,它就变回灰色对象了         。

这其实有点像之前讲过类似OopMap的思想    ,本质也是维护了个映射关系                       ,重新扫描的时候扫描这个映射关系就行了               ,不用全表扫描        。

原始快照

原始快照要破坏的是第二个条件,当灰色对象要删除指向白色对象的引用关系时                    ,就将这个要删除的引用记录下来                   ,在并发扫描结束之后   ,再将这些记录过的引用关系中的灰色对象为根                ,重新扫描一次                      。这也可以简化理解为                    ,无论引用关系删除与否      ,都会按照刚刚开始扫描那一刻的对象图快照来进行搜索            。

以上无论是对引用关系记录的插入还是删除            ,虚拟机的记录操作都是通过写屏障实现的    。写屏障                     ,我们之前讲记忆集与卡表的时候介绍过的         ,可以理解为Spring中的AOP        ,目前为止卡表状态的维护                      ,增量更新            ,原始快照都是基于写屏障                       。

另外    ,CMS使用的是增量更新                       ,G1使用的是原始快照               。

本篇文章就到这里               ,如果再遇见面试官问你类似的问题,你可以好好跟他扯皮咯。

如果本篇博客有任何错误和建议                    ,欢迎给我留言指正                    。文章持续更新                   ,可以关注公众号第一时间阅读                   。

声明:本站所有文章   ,如无特殊说明或标注                ,均为本站原创发布   。任何个人或组织                    ,在未征得本站同意时      ,禁止复制            、盗用                      、采集        、发布本站内容到任何网站         、书籍等各类媒体平台                。如若本站内容侵犯了原著者的合法权益            ,可联系我们进行处理                    。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
win10系统装win7双系统怎么装(在win7/win8下安装win10预览版双系统图文教程) 任务app平台怎么赚钱(任务**网站有哪些-手机**做任务赚钱,在家躺着收入破百,各种众包靠谱吗?)