你可以对比理解,
垃圾收集算法是去处理垃圾的,但是如何知道哪些是垃圾就需要去标记,如果你可以接受项目停顿,其实你也可以不用三色标记,但是很显然,说到底客户无法接受卡顿的程序
在并发标记的过程中,因为标记期间应用线程还在继续跑,对象间的引用可能发生变化,多标和漏标的情况就有可能发生。漏标的问题主要引入了三色标记算法来解决。 三色标记算法是把Gc roots可达性分析遍历对象过程中遇到的对象, 按照“是否访问过”这个条件标记成以下三种颜色:
黑色
表示对象已经被垃圾收集器访问过, 且这个对象的所有引用都已经扫描过。 黑色的对象代表已经扫描过, 它是安全存活的, 如果有其他对象引用指向了黑色对象, 无须重新扫描一遍。 黑色对象不可能直接(不经过灰色对象) 指向某个白色对象
灰色
表示对象已经被垃圾收集器访问过, 但这个对象上至少存在一个引用还没有被扫描过。
白色
表示对象尚未被垃圾收集器访问过。 显然在可达性分析刚刚开始的阶段, 所有的对象都是白色的, 若在分析结束的阶段, 仍然是白色的对象, 即代表不可达。
简要概括如下

这里的黑色很明确,就是存活对象,不能去动的
灰色是要清理掉的,白色作为垃圾要全部回收的
以上就是对象被标记后的去处
但是你要知道,对象被标记的时候,我们的程序可并没有停止哦
也就是虽然被标记了,但是你的业务代码也在修改对象引用,是不是尴尬了
就是在标记的时候是活的,但是标记之后,又被抛弃这个引用了,变成了垃圾,需要被回收,但是本次做完标记,只能把标记的处理掉,但是它不在本次的处理队列中,因而他就成了浮动的垃圾
就是还有一个问题,本来是个死的,结果被程序搞了个引用,程序活了,你再去删的时候,就有问题了,所以这种情况可能需要来个网子拦一下
好了,下面我们将对两种情况针对性分析
针对浮动垃圾,jvm允许它的存在
而对于加网子的事,提供了两种方案
第一种是增量更新
黑对象新增引用,要重新关注

第二种就是Snapshot At The Beginning

下面来一段总结
在并发标记过程中,由于用户线程会修改对象引用关系,可能导致三色标记出现漏标问题。JVM通过写屏障记录引用变化(如CMS的增量更新、G1的SATB),保证对象不会被错误回收;而在ZGC等收集器中,通过读屏障保证对象在移动过程中的访问正确性
那还会存在漏掉未处理或者误操作的吗,答案是会有漏的,但是漏掉的下次处理就好了,但是误删问题就没有了
在并发标记过程中,确实可能由于引用关系变化导致标记不精确,但 JVM 通过写屏障和最终的 remark 阶段保证不会发生漏标,从而避免误删活对象。而对于多标产生的浮动垃圾,JVM选择延迟回收,在下一次GC中处理,这是在停顿时间和回收精度之间的权衡。
好了关于三色标记的介绍就到这里了
