1,三色标记的应用场景:
三色标记算法是应用于并发标记阶段,用标记判断是不是垃圾。
(1)什么是并发标记阶段。七个阶段中第二阶段:
并发标记阶段的主要工作是,通过遍历第一个阶段(Initial Mark)标记出来的存活root对象,继续递归遍历老年代,并标记可直接或间接到达的所有老年代存活对象。
可以参考这篇文章:
Java之CMS GC的7个阶段
(2)什么是三色?
三色标记中的,三色分别代表着,垃圾回收的扫描程度和节点的标记状态,
黑色:表示该节点及其子节点已经完全扫描标记完成了,所以不再需要标记
灰色:表示该节点已经扫描标记完成了,但是子节点的尚未完成扫描标记(也就是没来得及:fields标记)
白色:表示还没有完成子节点
(3)三色标记的最严重的情况。
并发过程是非常复杂的,业务线程在不断运行,GC线程也在不断运行,由此可能会产生各种并发问题。
a,B->D消失,A->D增加
产生问题:
当B->D的引用消失之后,之前B作为灰色标记,但是他子节点没有D引用,那么D不会被扫描到,
当A->D的引用增加之后,之前A作为黑色标记,但是作为黑色标记不会再扫描,那么同样D节点被扫描。
所以,出现了这样一种情况,D不会被标记,也就意味着D可能被作为垃圾回收了。、
CMS解决:
当标记为黑色节点,再次指向新得对象的时候,将其标为灰色
也就说,将A重新标记为灰色,这样就可以顺着A标记可以找到D节点
两个过程图解
1,B ->D (B指向D的引用)消失:
将当成浮动垃圾
2,增加了A->D(A指向D的)引用
但是因为,A为黑色,所以D也不会被标记
3,将A重新标记为灰色(CMS解决方案,Incremental Update):
2,CMS解决方案(Incremental Update)天生bug
CMS在JDK1.9之后,就被移除掉了,
因为他有一个天生的难以修复bug
那就是:并发标记时候,会产生漏标
问题描述:
假设现在有两个垃圾回收线程A,B,
线程A将对象1标记为黑色,这个时候被迫停止,转到运行其他垃圾回收线程了,比如线程B
在A停止的过程中,
线程B将对象1标记为白色,
之后重新运行线程A。
那么就会导致一件什么事情发生呢?
这就会直接到指定,A以为对象1已经标记为黑色,不再对新的引用对象2扫描了,
对象2,未被标记
原文:
直接导致的后果是:
CMS在remark阶段,必须从扫描一遍。
解释:
那就是CMS在remark中,STW(stop the world)时间会比较长,甚至因为内存太大而时间特别长,小则半小时,多则几天,
如果出现这种情况那么CMS就没有意义了,他本来诞生就是想要完善STW并发过长的问题。
JIDK1.9之后,移除CMS
所以在JDK1.9之后移除了CMS,改为使用G1。