JVM 垃圾回收入门:对象死亡判断的底层逻辑
在 Java 开发中,JVM 垃圾回收机制不仅是面试的高频考点,更是理解内存管理的基石。很多人只背结论却不懂底层逻辑,一旦遇到追问就容易卡壳。我们直接从原理出发,拆解对象死亡的两种核心判断方式,顺便梳理几个高频追问,帮你把这块硬骨头啃下来。
为什么需要判断对象死亡?
JVM 的堆内存是有限的,如果创建的对象不再被使用,却一直占用内存,久而久之会导致内存泄漏,甚至触发 OOM(OutOfMemoryError)异常,导致程序崩溃。
因此,垃圾回收的核心前提就是:准确判断哪些对象已经'死亡'(不再被任何地方引用,失去使用价值),才能安全地回收其占用的内存,保证程序稳定运行。简单来说,判断对象死亡是垃圾回收的'前置操作',也是避免内存浪费的关键。
对象死亡判断的两大核心机制
JVM 判断对象死亡,主要依赖两种机制:引用计数法 和 可达性分析算法。其中,可达性分析算法是目前主流采用的核心方式,而引用计数法因自身缺陷被淘汰。
引用计数法(已淘汰)
原理
给每个对象分配一个'引用计数器'。当对象被引用一次,计数器值加 1;当引用失效(比如变量赋值为 null),计数器值减 1。当计数器值为 0 时,认为该对象已经死亡,可被回收。
示例
// 创建对象,计数器初始化为 1
Object obj = new Object();
// 新增引用,计数器变为 2
Object obj2 = obj;
// 引用失效,计数器变为 1
obj = null;
// 引用失效,计数器变为 0(对象可被回收)
obj2 = null;
致命缺陷:循环引用问题
引用计数法最大的问题是无法解决'循环引用'场景,这也是它被 JVM 淘汰的核心原因。
比如两个对象互相引用,但都不再被其他地方引用,此时它们的计数器值都为 1,无法被回收,导致内存泄漏:
class A {
private B b;
public void setB(B b) { this.b = b; }
}
class B {
private A a;
public void setA(A a) { this.a = a; }
}
// 循环引用
();
();
a.setB(b);
b.setA(a);
a = ;
b = ;


