java垃圾回收通过可达性分析算法判定对象存活:从gc roots(如栈中局部变量、静态字段、常量池引用、jni引用、synchronized锁对象)出发,沿强引用链搜索,可达对象存活,不可达对象可回收;该算法天然解决循环引用问题。

Java 垃圾回收机制通过可达性分析算法判断对象是否存活,核心逻辑是:从一组确定活跃的起点(GC Roots)出发,沿着强引用链向下搜索;能被访问到的对象视为存活,其余不可达对象即为可回收。
哪些对象可以作为 GC Roots
GC Roots 是判定的起点,必须是 JVM 认定“绝不会被回收”的活跃引用。主要包括:
- 虚拟机栈中局部变量表里的引用(如方法参数、本地变量)
- 方法区中静态字段引用的对象(如 public static Object cache)
- 方法区中常量池引用的对象(如字符串字面量 "hello")
- 本地方法栈中 JNI(Native 方法)持有的对象引用
- 被 synchronized 锁定的对象(即当前持有 monitor 的对象)
“可达”只看强引用链,不看业务逻辑
一个对象是否“可达”,不取决于它是否还在业务中使用,而只取决于是否存在一条由强引用构成的路径,从某个 GC Root 到达它:
- 例如:A → B → C,其中 A 是栈中局部变量(GC Root),B 是 A 的成员变量,C 是 B 的成员变量 —— 则 A、B、C 全部可达
- 若 A 被设为 null,且没有其他 GC Root 连向 B,则 B 和 C 同时变为不可达
- 软引用、弱引用、虚引用不参与可达性判定,它们只影响 GC 时的回收时机,不改变“存活”状态
循环引用不影响回收,这是可达性分析的关键优势
Java 不用引用计数,所以两个对象互相引用但无外部强引用时,仍会被正常回收:
- 比如 A.ref = B; B.ref = A;,之后 A = null; B = null;
- 只要 A 和 B 都不再被任何 GC Root 引用,它们就整体不可达,JVM 会回收二者
- 这与 Python 等语言不同,是可达性分析天然解决的问题,无需额外干预
JVM 内部用三色标记高效执行扫描
在实际标记阶段,JVM 使用三色标记法管理对象状态,确保不遗漏、不重复:
- 白色:尚未访问,初始状态;标记结束仍为白色,即为可回收对象
- 灰色:自身已发现,但其引用的字段还没扫描完(正在处理中)
- 黑色:自身和所有直接引用字段都已扫描完毕,确认存活
过程是从所有 GC Roots 开始涂灰入队,逐个取出灰色对象,将其引用的白色对象涂灰并入队,自身涂黑;直到灰色队列为空。最终黑色对象存活,白色对象待回收。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











