最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java中三色标记法 White Gray Black 在并发垃圾收集器中的漏标与错标风险
时间:2026-06-20 10:08:10 编辑:袖梨 来源:一聚教程网
三色标记法本身不引发漏标或错标,真正风险源于用户线程与GC线程并发修改引用导致“黑→白引用”约束被破坏;漏标(致命,致NPE)需黑色新增引用且灰色路径全断,错标即浮动垃圾(如栈帧销毁、新对象标黑),属可控延迟代价。
三色标记法本身不产生漏标或错标,真正引发风险的是用户线程与 GC 线程并发修改引用关系时,违反了“黑→白引用不可存在”这一核心约束。漏标会破坏程序正确性,必须拦截;错标(即多标)只导致浮动垃圾,属于可接受的延迟代价。
漏标:为什么致命,以及它发生的两个必要条件
漏标指本该存活的对象被误判为垃圾并回收,可能引发 NullPointerException 或数据损坏。它不会随机发生,而是严格依赖以下两个同时成立的条件:
- 一个黑色对象(已扫描完毕)在标记完成后,新增了一条指向某个白色对象的引用;
- 所有能到达该白色对象的灰色路径,在此之前已被切断(例如,原灰色父对象删除了对该白色对象的引用)。
此时,白色对象既无灰色上游可被继续扫描,又被新引入的黑色对象“遮蔽”,GC 不再访问它,最终被清除。
错标(多标):本质是浮动垃圾,不是错误
错标实际是“多标”,即把本该回收的对象标记为存活。它不威胁程序安全,只影响内存及时释放。典型场景包括:
立即学习“Java免费学习笔记(深入)”;
- 栈帧提前退出:方法执行结束,局部变量(GC Root)出栈,其引用的对象若已在并发标记中被标为灰色或黑色,就不会再被重新评估;
- 新对象直接标黑:并发标记或清理阶段新分配的对象,JVM 通常默认设为黑色(视为本轮必活),哪怕它几毫秒后就失去所有引用;
- 引用断开晚于标记:如
objA.fieldB = null发生在 GC 已将 B 标灰之后,B 及其子图仍会被完整扫描并标黑。
写屏障:用来守住“黑→白不可达”这条红线
所有现代并发收集器(CMS、G1、ZGC)都依赖写屏障(Write Barrier)来干预引用变更,防止漏标。不同策略应对方式不同:
-
SATB(Snapshot-At-The-Beginning):在引用被修改前,记录下即将消失的旧引用(如
objA.fieldB = null前把 B 记入缓冲区),确保 B 不被漏掉; -
增量更新(Incremental Update):在新增引用时(如
objC.fieldD = objB),若 objC 是黑色,就把 objB 重新推回灰色队列,补扫一次。
二者目标一致——维护三色不变量,但实现时机和开销不同。SATB 更侧重“保底不丢”,增量更新更侧重“及时补救”。
为什么浮动垃圾可以容忍,而漏标绝不允许
浮动垃圾只是延迟回收,下一轮 GC 必然识别并清理,且不增加内存泄漏风险;漏标则直接破坏可达性语义,等价于把正在使用的对象内存归还给系统,后续访问必然出错。因此 JVM 宁可多花一点写屏障开销、多做一次重新标记(Remark),也要堵死漏标通路。这也是为什么 CMS/G1 的 Remark 阶段虽短,却必不可少。
相关文章
- 《明日方舟终末地》陈千语怎么样-陈千语值得培养吗 07-04
- 《明日方舟终末地》余烬怎样配队-余烬阵容搭配推荐 07-04
- 《明日方舟终末地》骏卫怎么样-骏卫值得培养吗 07-04
- 《明日方舟终末地》莱万汀怎样配队-莱万汀强力配队推荐 07-04
- 《明日方舟终末地》原木怎样获得-原木获得方法 07-04
- 《长生天机降世》太虚境十天智遗迹幻境通关攻略-详细打法解析 07-04