可达性分析算法是jvm判断对象是否存活的核心方法,从gc roots(如虚拟机栈局部变量、静态字段、常量池引用、jni引用等)出发沿引用链标记可达对象,未被标记的即为可回收垃圾,天然解决循环引用问题。

JVM 判断对象是否“死亡”,核心是看它是否还能被程序访问到,而不是靠对象自己声明“我不用了”。目前所有主流 JVM(比如 HotSpot)都只采用可达性分析算法,不使用引用计数法。
可达性分析:从 GC Roots 出发找活路
JVM 会选定一组必须存活的“根对象”(GC Roots),然后顺着所有引用链向下扫描。只要某个对象能通过任意一条引用路径连到 GC Roots,它就被认为“还活着”;反之,如果从任何 GC Root 都无法触达该对象,它就被标记为“已死”,后续可被回收。
常见的 GC Roots 包括:
- 虚拟机栈中正在使用的局部变量所引用的对象
- 方法区中类的静态字段(static 变量)引用的对象
- 方法区中常量池里的字符串常量或类字面量引用的对象
- 本地方法栈(JNI)中正在使用的 Native 引用的对象
引用类型决定“死亡”的节奏
即使对象不可达 GC Roots,不同引用类型也会让回收行为有差异:
- 强引用:只要存在,对象绝不会被回收;只有所有强引用全部断开,才可能进入“待回收”状态
- 软引用:内存充足时不回收;触发 Full GC 且内存仍不足时,才会回收关联对象
- 弱引用:只在下一次 GC 时就被回收,不管当前内存是否紧张
- 虚引用:仅用于接收对象被回收的通知,不影响对象生命周期
两次标记与 finalize 的特殊处理
某些对象可能被第一次标记为“不可达”,但若它重写了 finalize() 方法且尚未执行过,JVM 会将它放入 F-Queue 队列,由低优先级线程尝试执行 finalize()。如果在此过程中对象重新与 GC Roots 建立了有效引用(比如把自己 this 赋给某个静态变量),它就能“复活”。否则,第二次标记后才真正确认死亡。
注意:从 Java 9 开始,finalize() 已被标记为废弃,不推荐使用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











