JVM三?标记
三?标记:是?种逻辑上的抽象,是一种分析工具,理解可达性分析法 是怎么分析对象是否可以被回收用的
将每个内存对象分成三种颜?:
-
??:??未标记完。 -
灰?:??标记完了,但是成员变量还没有完全标记完。 -
??:表示??和成员变量都已经标记完毕。
三?标记大致步骤
-
开始之前,将所有对象都标记为白色 -
分析开始,将GC roots对象标记为黑色,黑色的下一个会被染色灰色,表示下次分析 -
分析到灰色,将灰色变成黑色,将灰色的下一个染成灰色 -
以此类推,知道走完所有引用链,扫描完后,还是白色的对象,为可回收对象
三色标记-漏标
什么算漏标 -> 标记的过程中,有其他线程修改了引用链,导致本该标记上为黑色的节点没有标记上最后还是白色被当作垃圾对象回收了
-
上图 -> 正常来说 -> 3的下一个引用链是4 -
另一个线程来了 -> 3的引用链断开 了与4的链接,连到1上去了 -
本应该3 -> 4,现在因为其他线程的问题,导致1 -> 4 -
但是1的对象位置已经分析完成了(已经变成了黑色) -
程序已经遍历到3 的位置了,不可能再回去,重新将4染色为灰色准备判断 -
就会导致4对象明明在这条引用链上,最后却要被判断为白色,而被垃圾回收,程序出问题
如何解决漏标?
很多地方你都看到了这两句话: 同时满足的情况下会产生"对象消失"
- CMS垃圾回收器-增量更新 -> 破坏:赋值器
插入了一条或者多条 黑色对象到白色对象的引用
-
如果你这次新增 了对象的引用,我就会将你这次新增跟的部位记录 ,修改为灰色,等待重新检查标记的时候,再一次检查标记
- 注意: 看好这个名字叫做增量更新,它只在乎增,它不在乎减
- 什么意思呢? 你就可以
加一根线 ,加在哪里我都可以记录,你新new一个对象我也可以 - 但是,
你要是去掉一根线,我可不管你 - 所以你要是去掉3 -> 5的那条线,3丶5依旧是黑色,依旧是不会被垃圾回收的
-
第二次重新标记的时候,遍历到1的位置,判断为灰色,又重新扫描,将1变成黑色,将4变成灰色,再黑色 -
最终所有的都完成标记
- G1垃圾回收器-原始快照 ->破坏: 赋值器
删除了全部 从灰色对象到白色对象的直接引用或者间接引用
-
与增量更新有些相反的操作,增量更新只记录增加的引用,而原始快照只记录删除的记录 -
如果你要去掉3 -> 4的这条引用,我会记录下这条删除,我记录好之后,你可以删除 -
重点来了 -> 重新标记阶段,我会查看记录删除的这些位置,将他们重新标记为灰色 -
然后我将删除的部分又变成黑色了,就是原始快照,中间删除了我都不管,给你加回来
- 就有人问了,这不是出现浮动垃圾了吗?
- 各位,什么是浮动垃圾?CMS一次没有清理完叫浮动垃圾
- 可是G1哎,它是G1哎,它从一开始就没准备一次清理完垃圾
- 它的目标就是清理多一点垃圾的那块内存
- 浮动垃圾?有又怎么了,影响吗?G1都不用管什么浮动垃圾,G1还先给你准备点垃圾不帮你回收呢
增量更新和原始复制从来都是为了解决漏标的问题,从来没说哪个方法会解决浮动垃圾的问题 如果有解决浮动垃圾问题,也一定不是这里两个方法解决的
|