JVM不使用引用计数法而采用可达性分析算法,因其能天然解决循环引用问题且避免并发更新开销;该算法以GC Roots为起点沿强引用链搜索,不可达对象即被标记为可回收。

JVM 不使用引用计数法,只用可达性分析算法来判断对象是否存活。这是由 Java 虚拟机规范和 HotSpot 实现共同决定的,不是配置或版本差异导致的。
核心区别在于设计目标和实际可行性
引用计数法靠“数引用个数”判定对象是否可回收;可达性分析算法靠“能否从根节点触达”判定对象是否存活。
- 引用计数法:每个对象维护一个整型计数器,被引用一次就 +1,引用失效就 -1;计数归零即视为垃圾。
- 可达性分析算法:以 GC Roots(如栈中局部变量、静态字段、JNI 引用等)为起点,沿引用链向下搜索;无法到达的对象才被标记为可回收。
为什么 JVM 放弃引用计数法
它在理论上简单高效,但有两个硬伤无法绕过:
- 循环引用问题:A 持有 B,B 持有 A,二者再无外部引用,本该回收,但计数器都不为 0,导致内存泄漏。
- 并发更新开销大:每次引用赋值或置 null 都要原子增减计数器,影响性能,尤其在多线程场景下需额外同步成本。
可达性分析算法的实际运作方式
它不依赖对象自身状态,而是全局扫描引用关系图:
- GC Roots 包括:虚拟机栈中引用的对象、方法区中类静态属性引用的对象、常量池中引用的对象、本地方法栈中 JNI 引用的对象。
- 一旦某个对象与所有 GC Roots 之间不存在任何引用路径(即不可达),哪怕它被其他“死对象”引用,也会被回收。
- 那个经典的
objA.instance = objB; objB.instance = objA;示例,在调用System.gc()后,两个对象确实会被回收——这正是可达性分析生效的直接证据。
四种引用类型是基于可达性分析之上的增强机制
强、软、弱、虚引用不是独立的判定算法,而是对“是否可达”的细化分级,影响 GC 在不同内存压力下的回收行为:
- 强引用:只要可达,绝不回收。
- 软引用:内存不足时才回收,适合缓存。
- 弱引用:GC 时只要不可达(哪怕内存充足)就回收。
- 虚引用:不阻止回收,仅用于接收回收通知。


















