Java垃圾回收通过可达性分析算法判断对象存活:从GC Roots(如虚拟机栈局部变量、静态变量、常量池引用、JNI全局引用、活跃线程及锁对象)出发,沿强引用链搜索,可达即存活,不可达则标记为可回收。

Java 垃圾回收(GC)判断对象是否可达,核心是可达性分析算法:从一组固定的起点(GC Roots)出发,沿着强引用链向下搜索;能被任何一条引用链触达的对象,即为“可达”,视为存活;否则标记为不可达,进入回收候选。
哪些对象算 GC Roots?
GC Roots 是 JVM 认为“必须存活、绝不能被回收”的锚点,主要包括:
- 虚拟机栈中正在使用的局部变量、方法参数所引用的对象(注意:方法执行结束 → 栈帧弹出 → 这些变量立即失效)
- 方法区(元空间)中的静态变量、常量池里的字符串常量等引用的对象
- 本地方法栈中 JNI 的全局引用(JNI 局部引用在 native 方法返回后自动释放,不构成稳定 Root)
- 正在运行的 Java 线程本身,以及它持有的锁对象(如 synchronized 持有的 monitor 对象)
怎么才算“能被触达”?
“可达”只看强引用链是否存在,不看代码写法或对象是否显式置 null:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 只要存在至少一条从某个 GC Root 出发、全部由强引用组成的路径连到该对象,它就存活
- 循环引用(如 A ⇄ B)不影响判定——若外部无 GC Root 连入整个环,整组对象仍不可达
- final 字段初始化完成后不可变,但若字段值被设为 null,原引用链即被切断
- 集合中移除元素(如 list.remove(obj))后,若再无其他强引用,该对象立刻失去 Root 支撑
不可达 ≠ 立刻回收
一次不可达判定只是回收流程的起点,后续还有:
立即学习“Java免费学习笔记(深入)”;
- 第一次标记:进入“待回收队列”,检查是否重写了 finalize()(已弃用)或注册了 Cleaner
- 第二次标记:若对象在第一次标记期间重新与 GC Root 建立强引用(极少见),可“自救”一次;否则正式列为可回收
- 真正回收时机由 JVM 决定——取决于堆内存压力、GC 策略(如 G1 的 Region 回收)、配置参数等,开发者无法强制
本质上,JVM 不是在找“垃圾”,而是在标记“活人”。所有没被标记的,才是 GC 要清理的目标。这个过程天然规避循环引用问题,也解释了为什么简单地写 obj = null 并不能保证对象马上消失。

















