ZGC标记阶段完全不处理弱引用和软引用的目标对象可达性,仅沿强引用链遍历;其引用处理是独立后置的并发阶段,分阶段解耦且零干预标记。

ZGC在标记阶段根本不处理弱引用和软引用的目标对象是否可达——它压根不看它们。
标记阶段只认强引用链
ZGC的并发标记(Concurrent Mark)从GC Roots出发,仅沿着强引用构成的路径遍历对象图。WeakReference和SoftReference本身是普通Java对象,它们的referent字段(即被引用的目标对象)不会被标记线程访问或追踪:
- 标记线程不会调用
WeakReference.get()或SoftReference.get(); - 目标对象是否存活,完全取决于是否存在至少一条强引用链能到达它;
- WeakReference/SoftReference对象自身若被局部变量、静态字段等强引用持有,它们自己会被正常标记为存活,但这不影响其所指对象的标记结果。
弱/软引用的处理是独立且后置的
ZGC把引用类型清理作为单独阶段,在并发标记完成之后执行:
- 该阶段称为“非强引用并发处理”(Concurrent Reference Processing),专门扫描并分类软、弱、虚、Final引用;
- 此时才检查:某个对象是否仅被弱引用或软引用持有,且无任何强引用路径;
- 满足条件的对象被标记为待回收,其对应的Reference对象被加入注册的
ReferenceQueue(若已注册); - 整个过程是并发的,不阻塞应用线程,也不干扰主标记流程。
内存压力决定软引用是否清理,弱引用则“见光就清”
虽然处理是并发的,但实际清除动作有策略差异:
立即学习“Java免费学习笔记(深入)”;
-
弱引用:只要在引用处理阶段判定目标对象无强可达路径,就立即清除其
referent字段,并入队; -
软引用:ZGC会结合当前堆使用率与软引用的
timestamp(由JVM维护),仅在内存真正紧张时批量清理——这避免了缓存过早失效,也避免了频繁触发引用处理开销。
不卡顿的关键:零干预+分阶段+读屏障保障
ZGC能做到高效,靠的是三重设计:
- 零干预标记:弱/软引用不参与三色标记过程,不存在“重构链条”或回溯重扫;
- 分阶段解耦:引用处理与对象标记分离,各自调度、各自并发;
-
读屏障保障快照一致性:即使应用线程在标记中修改引用关系(如赋值
ref.set(null)),ZGC通过读屏障捕获变更,确保标记结果反映逻辑上一致的堆状态,无需Stop-The-World校正。


















