jvm垃圾回收可靠性由多层机制协同保障:可达性分析确保对象判定准确,安全点/区域保障执行一致性,三色标记配合写屏障维护并发正确性,分级晋升策略提供兜底容错。

JVM 垃圾回收过程的可靠性,不是靠单一环节实现的,而是由一套协同工作的保障机制共同支撑——从对象生死判定的准确性,到回收执行时的一致性与安全性,再到并发场景下的状态同步,每一层都设防。
可达性分析的严谨起点
JVM 不依赖易出错的引用计数法,而是采用可达性分析(Reachability Analysis)作为判断对象是否存活的唯一标准。它以一组严格定义的 GC Roots 为起点,包括:
- 虚拟机栈中每个栈帧的局部变量表所引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量池引用的对象(如字符串常量)
- 本地方法栈中 JNI(Native 方法)引用的对象
- 正在执行的同步锁(monitor)所持有的对象
只有当一个对象无法通过任何一条引用链到达 GC Roots 时,才被认定为可回收。这种“自上而下”的遍历方式从根本上规避了循环引用导致的漏判问题,是可靠性的第一道防线。
安全点与安全区域的执行控制
垃圾回收必须在程序状态一致、对象引用关系稳定的时刻进行,否则可能误判或破坏数据。JVM 为此引入了 安全点(Safepoint) 和 安全区域(Safe Region):
- 安全点是代码中某些特定位置(如方法调用、循环跳转、异常抛出前),JVM 会在此处检查是否需要暂停线程;所有用户线程必须运行到最近的安全点才能被挂起
- 安全区域则用于解决线程处于长时间阻塞(如 sleep、wait)时无法响应安全点请求的问题,允许线程在进入该区域后自主声明“安全”,无需轮询
这意味着 GC 触发后,并非立即全局停顿,而是等待线程主动抵达可控位置再统一暂停——既保证了堆状态的快照一致性,又避免了粗暴中断带来的不确定性。
三色标记与增量更新/原始快照
在 CMS、G1、ZGC 等并发收集器中,GC 线程与用户线程同时运行。为防止标记过程中因用户线程修改引用而导致对象漏标(即本该回收却未被标记),JVM 使用 三色标记法 并辅以写屏障(Write Barrier)技术:
- 白色:尚未访问,可能是垃圾
- 灰色:已访问但子引用未全部扫描完
- 黑色:已访问且所有子引用均已扫描完毕
当用户线程在并发标记期间修改引用(如将黑色对象指向白色对象),不同收集器采取不同策略保障完整性:
- G1/CMS 使用 增量更新(Incremental Update):把被修改的黑色对象重新标记为灰色,后续继续扫描其子引用
- ZGC/Shenandoah 使用 原始快照(Snapshot-At-The-Beginning, SATB):在标记开始时记录所有即将被覆盖的引用,确保初始可达的对象不会丢失
这些机制让并发 GC 在不牺牲正确性的前提下,大幅降低停顿时间。
晋升与担保失败的兜底处理
新生代 GC(Minor GC)后,若存活对象无法全部放入 Survivor 区,JVM 会按规则晋升至老年代。但老年代空间不足时,不能简单失败——它有一套分级担保策略:
- 先检查老年代剩余空间是否 ≥ 当前所有待晋升对象总大小 → 直接晋升
- 否则,参考历史晋升平均值,若剩余空间 ≥ 该均值 → 尝试“冒险晋升”(允许部分失败)
- 若仍不满足,则触发 Full GC,清理整个堆并整理空间;若 Full GC 后仍无法容纳,才抛出
OutOfMemoryError
这一流程确保内存分配请求不会因 GC 中间状态而无故失败,提升了系统行为的可预测性与鲁棒性。











