如何深度解构主流虚拟机放弃引用计数而倒向可达性分析的底层考量

胖强吖_5810

胖强吖_5810

2026-05-21

749人浏览

原创

主流虚拟机采用可达性分析而非引用计数,根本原因是引用计数无法解决循环引用导致的内存泄漏——a与b互相引用时计数器永不归零,造成不可逆oom;而可达性分析从gc roots出发遍历,天然规避循环陷阱,且配合写屏障等机制可确保标记精度。

主流虚拟机放弃引用计数、采用可达性分析,根本原因不是技术“先进性”的选择,而是为解决循环引用导致的内存泄漏这一硬伤——它在java这类面向对象语言中无法回避,且一旦发生就不可逆。

循环引用直接导致内存泄漏

引用计数法要求每个对象维护一个整型计数器,每次赋值或置空都需原子更新。但当对象A持有B、B又持有A时,即使外部所有引用(如栈变量)均已清空,A和B的计数器仍各为1,永远不为0。虚拟机无法判定它们已脱离业务逻辑,只能长期驻留堆中。这种泄漏在长周期服务(如Web容器、中间件)中会持续累积,最终触发OOM。

  • 典型场景:监听器注册后未解绑、内部类隐式持外层引用、缓存Map中key-value互引
  • 实测验证:《深入理解Java虚拟机》中经典示例运行后,System.gc()仍能回收互相引用的objA/objB,反向证明HotSpot未使用引用计数

并发与性能代价被低估

引用计数看似“即刻回收”,但在多线程环境下,每次引用赋值(obj.field = other)或局部变量重赋(x = y)都需对目标对象计数器做CAS操作。高并发业务中,这会引发大量缓存行失效(false sharing)和锁竞争。HotSpot实测表明,该开销在吞吐密集型应用中可抬升GC线程外的CPU消耗达12%以上。

DreamStudio
DreamStudio

一款基于Stable Diffusion生态的在线AI图像生成工具,帮助用户通过文字描述创建艺术图像和视觉素材。

下载
  • 对比:可达性分析仅在GC停顿窗口内集中遍历,引用关系变更无需实时同步
  • 补充:Python虽用引用计数,但仅对不可含引用的简单类型(str/int)启用;list/dict等复合结构必须配合mark-sweep兜底,本质是混合策略

GC Roots提供稳定、可枚举的起点

可达性分析依赖一组明确、静态可识别的根集合(GC Roots),包括栈帧局部变量、静态字段、常量池项、JNI句柄等。这些位置天然具备“强存活”属性,且生命周期与线程/类加载器绑定,无需额外维护状态。从它们出发做图遍历,既能覆盖全部活跃引用路径,又能天然规避循环陷阱——A→B→A这条环形链,只要A、B均未被任何Root触达,整条链就被整体判为不可达。

  • 关键细节:GC Roots本身位于堆外(栈、方法区、本地方法栈),确保分析过程不依赖堆内对象状态
  • 延伸影响:该设计为分代收集、增量更新(如CMS、G1的SATB)提供了基础支撑

误标与漏标问题已有成熟应对

有人质疑可达性分析存在“漏标”(存活对象被错杀)或“误标”(死亡对象被错活),但这属于并发标记阶段的工程问题,而非算法缺陷。现代虚拟机通过写屏障(Write Barrier)、三色标记法、增量更新(IU)或原始快照(SATB)等机制严格约束,使标记精度趋近于100%。而引用计数的循环引用问题,是算法层面无解的结构性缺陷。

  • 例如G1在并发标记时,用SATB记录被修改的引用字段,确保不会遗漏新建立的引用链
  • ZGC更进一步,将标记过程完全并发化,停顿时间压至10ms内,仍未动摇可达性分析根基

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10877

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

8002

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6952

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1164

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

948

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1416

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2869

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20151

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1255

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程