java不采用引用计数法,因其无法解决循环引用导致的内存泄漏,且频繁更新计数器带来性能开销;实际使用基于gc roots的可达性分析法,从根出发遍历引用链,天然规避循环引用问题。

Java 的垃圾回收器(GC)实际上并不使用引用计数法来判定对象是否“死亡”。这是 Java 规范和主流虚拟机(如 HotSpot)的明确设计选择。
为什么 Java 不用引用计数法?
引用计数法原理简单:每个对象维护一个计数器,每新增一个引用就 +1,引用失效就 -1;计数归零即认为可回收。但它存在两个致命缺陷:
- 无法处理循环引用:A 持有 B 的引用,B 又持有 A 的引用,即使二者外部再无引用,计数器都不为 0,导致内存泄漏
- 计数器增减开销大且需线程安全:每次赋值、作用域退出、异常跳转等都要更新计数,频繁同步影响性能
Java 实际使用的判定方法:可达性分析(Reachability Analysis)
HotSpot VM 使用的是根可达性分析算法,核心逻辑是:
- 从一组称为“GC Roots”的对象出发(如栈帧中的局部变量、静态字段、JNI 引用等)
- 沿着引用链向下搜索所有可达对象
- 不可达的对象被标记为“可回收”,后续由 GC 线程清理
这种方法天然解决循环引用问题,也更适合现代 JVM 的分代、并发、增量等复杂回收策略。
引用计数在 Java 中的“影子存在”
虽然 JVM 不用它做生死判定,但某些场景会间接体现类似思想:
- 软引用(SoftReference)、弱引用(WeakReference)、虚引用(PhantomReference):它们的回收时机由 GC 决定,但依赖于当前内存压力或引用队列状态,不是靠计数器
- 部分 JVM 调试工具或第三方分析器:可能在采样时统计引用数量辅助诊断,但这属于监控手段,不参与 GC 决策
- 某些嵌入式或特殊 JVM 移植版本(极少见):理论上可实现引用计数,但不符合标准 Java 语义,也不被 Oracle/OpenJDK 支持
开发者需要注意什么?
你不需要、也不能手动触发或干预引用计数——因为 JVM 根本没实现它。应关注的是:
- 避免显式保留无用引用(如静态集合不断 add、监听器未 remove)
- 合理使用 WeakHashMap 缓存,利用弱引用自动清理机制
- 理解 finalize() 已被废弃,Cleaner 或 try-with-resources 是更可靠的资源清理方式
- 通过 jstat、VisualVM、JFR 等工具观察实际 GC 行为,而非假设“计数归零才回收”
不复杂但容易忽略:Java 的对象生死,从来不由“谁还指着我”决定,而取决于“谁能从根走到我”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











