三色标记法是实现并发垃圾回收的核心机制,通过白(未访问/待回收)、灰(已访问、子引用未全扫描)、黑(已访问且子引用全扫描)三种状态动态推进可达性分析,在gc线程与应用线程并发执行时确保标记准确性,以换取极短stw时间。

三色标记法是实现异步(并发)垃圾回收的核心机制,它让 GC 线程和应用线程能同时运行,避免长时间 Stop-The-World。理解它的关键不在于颜色本身,而在于每种颜色所代表的**可达性分析进度状态**,以及这些状态在并发环境下的动态变化。
三色标记的本质含义
所有对象初始为白色,表示“尚未确认是否可达”。标记过程就是把对象从白→灰→黑逐步推进:
- 白色:未被 GC 访问过;若标记结束仍为白色,即不可达,是待回收垃圾
- 灰色:已被访问,但其直接引用的对象尚未全部检查;它是 GC 当前的工作队列
- 黑色:自身及所有直接引用对象都已检查完毕;GC 认定它是存活的,不再重新扫描
为什么需要“异步”?
传统 STW 标记必须暂停所有应用线程,堆越大,停顿越久。三色标记把大块标记任务拆成小步,允许 GC 线程与用户线程交错执行——代价是引入了引用关系变更带来的不确定性。
“浮动垃圾”的典型产生场景
浮动垃圾指本该本轮回收、却因标记“提前介入”而被误判为存活的对象。它不破坏程序正确性,只造成内存延迟释放。常见情形有两类:
-
GC 快于应用线程断开引用:比如对象 A(灰色)正被扫描,GC 读到它对 B 的引用,立即将 B 涂灰;紧接着应用线程执行
A.b = null,B 实际已失去所有强引用,但因已被涂灰,后续会被递归标记为黑,逃过本轮回收 - 并发标记开始后的新对象:新分配的对象(如方法内新建的临时对象)在标记中后期才出现,通常直接置为黑色(视为“默认存活”),即使它很快因作用域结束而变成垃圾,也会留到下一轮 GC 才清理
浮动垃圾不是缺陷,而是权衡结果
它用少量内存冗余,换来了极短的 GC 停顿。JVM 不需专门处理它——下一轮 GC 时,这些对象若仍不可达,自然会进入白色并被回收。CMS、G1、ZGC 等现代收集器都接受这一设计,重点是通过写屏障等机制严防更危险的“漏标”问题。










