Java垃圾回收中对象存活判定依赖可达性分析算法,而非引用计数法;它从GC Roots(如虚拟机栈局部变量、方法区静态变量、JNI引用等)出发单向搜索引用链,不可达对象需经两次标记才被回收,且finalize()已弃用。

Java垃圾回收中,对象是否存活不靠“有没有被引用”,而看它能否从一组固定起点被“触达”。主流JVM只用可达性分析算法,引用计数法因无法处理循环引用已被弃用。
可达性分析:从GC Roots出发找活对象
判定逻辑是单向搜索:以若干可信的“根对象”(GC Roots)为起点,顺着所有引用链向下遍历。能被遍历到的对象视为存活;遍历不到的,才进入待回收候选队列。
- 虚拟机栈中正在使用的局部变量、方法参数
- 方法区里的静态变量、字符串常量池中的常量
- 本地方法栈中JNI调用所持有的对象
- 被synchronized锁住的对象、JVM内部关键对象(如Class对象、异常实例等)
不是“不可达”就立刻回收
一个对象被判定为不可达后,不会马上清除,而是要经历两次标记:
- 第一次标记:检查该对象是否重写了finalize()方法且尚未执行。若满足,放入F-Queue队列,等待Finalizer线程调用其finalize()
- 第二次标记:在finalize()执行期间,如果对象重新与GC Roots建立了引用(比如把自己赋给某个静态字段),就会被移出回收集合;否则,真正标记为可回收
注意:自JDK 9起,finalize()已被标记为废弃,实际项目中应避免使用,因此绝大多数对象只需一次可达性判断即可确认回收资格。
不同引用类型影响判定结果
强、软、弱、虚四种引用,在可达性分析中扮演不同角色:
- 强引用:只要存在,对象一定不可回收
- 软引用:内存不足时才可能被回收,常用于缓存
- 弱引用:下一次GC时无论内存是否充足都会回收
- 虚引用:不影响对象存活时间,仅用于接收回收通知
分代回收如何配合存活判定
存活判定是回收的前提,而分代策略决定了何时、用什么算法回收:
- 新生代对象多数朝生暮死,采用复制算法(Minor GC),依赖快速的可达性扫描+复制存活对象
- 老年代对象存活率高,采用标记-整理算法(Major GC),先做完整可达性分析,再压缩整理内存
- 每次GC前,JVM都必须先明确哪些对象“还活着”,这个过程本身不区分代,但扫描范围和触发条件由分代策略控制

















