JVM 为什么不使用引用计数算法?——深入解析 GC 策略
在 Java 中,垃圾回收(Garbage Collection, GC)是一个至关重要的功能,它能够自动管理内存,回收不再使用的对象,从而防止内存泄漏。然而,在垃圾回收的实现上,JVM 并未采用引用计数算法(Reference Counting),而是使用了可达性分析算法(Reachability Analysis)。
那么,为什么 JVM 选择可达性分析,而不是引用计数?这篇文章将深入探讨引用计数的原理、局限性,以及 JVM 采用可达性分析的原因。
1. 什么是引用计数算法?
1.1 引用计数算法的基本原理
引用计数是一种简单且高效的垃圾回收策略,它的核心思想是:
-
每个对象维护一个引用计数器,记录有多少个变量或其他对象引用它。
-
当有新的引用指向该对象时,计数器 +1。
-
当一个引用失效(比如变量赋值为
null)时,计数器 -1。 -
当计数器降为 0 时,说明该对象不再被任何变量或对象引用,可以被垃圾回收。
1.2 引用计数的示例
class ReferenceCountingGC {public Object instance = null;private static final int _1MB = 1024 * 1024;// 占用内存,以便观察 GC 发生情况private byte[] bigSize = new byte[2 * _1MB];public static void testGC() {ReferenceCountingGC objA = new ReferenceCountingGC();ReferenceCountingGC objB = new ReferenceCountingGC();objA.instance = objB;objB.instance = objA;objA = null;objB = null;System.gc();}public static void main(String[] args) {testGC();}
}
按照引用计数算法的逻辑:
-
objA和objB互相引用,导致它们的引用计数始终不为 0。 -
即使
objA = null; objB = null;,它们仍然引用彼此,引用计数不会降为 0。 -
结果:垃圾回收器无法回收这两个对象,导致内存泄漏。
2. JVM 为什么不采用引用计数算法?
2.1 关键问题:循环引用问题
正如上面的例子所示,引用计数算法无法处理循环引用(Circular Reference)。
在 Java 这种广泛使用对象引用的语言中,循环引用的情况很常见。如果采用引用计数算法,会导致大量的对象无法被正确回收,从而引发内存泄漏,严重影响应用程序的稳定性。
解决方案?
-
可达性分析算法(Reachability Analysis),也称作可达性遍历。
3. 可达性分析算法(JVM 的 GC 方案)
3.1 可达性分析的基本原理
JVM 采用可达性分析算法来判断对象是否存活,其核心思想是:
-
以一组**根对象(GC Roots)**作为起点。
-
从 GC Roots 开始遍历对象的引用链(Reference Chain)。
-
可达的对象被认为仍然存活,不可达的对象则会被回收。
GC Roots 包含哪些对象?
-
栈上的局部变量(方法内的变量)。
-
静态变量(属于类的静态字段)。
-
运行时常量池中的引用(比如字符串常量池
String Table)。 -
本地方法栈 JNI 引用(Native 代码引用的对象)。
-
JVM 内部特殊对象(如类加载器、异常对象等)。
3.2 可达性分析示例

4. JVM 的四种引用类型
为了更好地管理对象,Java 1.2 之后引入了四种引用类型:
4.1 强引用(Strong Reference)
Object obj = new Object();
-
只要强引用存在,GC 永远不会回收该对象。
4.2 软引用(Soft Reference)
SoftReference<Object> softRef = new SoftReference<>(new Object());
-
适用于缓存,内存不足时才会被回收。
4.3 弱引用(Weak Reference)
WeakReference<Object> weakRef = new WeakReference<>(new Object());
-
下一次 GC 就会回收,用于存储敏感数据(如
ThreadLocal)。 -
ThreadLocal中的ThreadLocalMap采用了弱引用,防止内存泄漏。
4.4 虚引用(Phantom Reference)
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), new ReferenceQueue<>());
-
对象被 GC 回收时会进入
ReferenceQueue,用于监控对象回收情况。 -
常用于管理堆外内存或跟踪对象销毁。
5. 结论
-
JVM 不使用引用计数算法的主要原因是:无法解决循环引用问题。
-
JVM 采用可达性分析算法,通过 GC Roots 遍历对象引用链来判断对象是否存活。
-
JVM 引入四种引用类型,以增强垃圾回收的控制能力,适应不同场景需求。
JVM 的 GC 机制不断优化,比如 G1、ZGC 采用了更先进的垃圾回收策略,使得 Java 的内存管理更高效。
相关文章:
JVM 为什么不使用引用计数算法?——深入解析 GC 策略
在 Java 中,垃圾回收(Garbage Collection, GC)是一个至关重要的功能,它能够自动管理内存,回收不再使用的对象,从而防止内存泄漏。然而,在垃圾回收的实现上,JVM 并未采用引用计数算法…...
【HarmonyOS NEXT】EventHub和Emitter的使用场景与区别
一、EventHub是什么? 移动应用开发的同学应该比较了解EventHub,类似于EventBus。标准的事件广播通知,订阅,取消订阅的处理。EventHub模块提供了事件中心,提供订阅、取消订阅、触发事件的能力。 类似的框架工具有很多…...
01-系统编程
一、程序和进程的区别: window系统: 1、程序存储在硬盘中,文件格式为.exe后缀,静态的 2、进程运行在内存中,动态的 Linux系统 1、程序存储在硬盘中,文件格式为.ELF(可执行的链接文件&#…...
Linux编译器gcc/g++使用完全指南:从编译原理到动静态链接
一、gcc/g基础认知 在Linux开发环境中,gcc和g是我们最常用的编译器工具: gcc:GNU C Compiler,专门用于编译C语言程序g:GNU C Compiler,用于编译C程序(也可编译C语言) 📌…...
UMI-OCR Docker 部署
额外补充 Docker 0.前置条件 部署前,请检查主机的CPU是否具有AVX指令集 lscpu | grep avx 输出如下即可继续部署 Flags: ... avx ... avx2 ... 1.下载dockerfile wget https://raw.githubusercontent.com/hiroi-sora/Umi-OCR_runtime_linux/main/Do…...
26考研|数学分析:定积分及应用
这一部分作为数学分析的灵魂,在数学分析的计算中,绝大部分的问题都可以转换成定积分的计算问题,所以在这部分的学习中,一定要注意提升计算能力,除此之外,由积分引出的相关积分不等式也是分析的重点和难点&a…...
React Hooks使用方法:useState,useRef,useEffect,useReducer,useContext用法实战案例
react hooks介绍,包括了state,ref,effect,reducer,context等常见hooks,也包括forwardRef和createContext用法,下面看代码吧,我用的是js写的。每个hook都做了个案例。 // 使用state来…...
线程池详解:在SpringBoot中的最佳实践
线程池详解:在SpringBoot中的最佳实践 引言 在Java并发编程中,线程池是一种非常重要的资源管理工具,它允许我们在应用程序中有效地管理和重用线程,从而提高性能并降低资源消耗。特别是在SpringBoot等企业级应用中,正…...
扩展卡尔曼滤波
1.非线性系统的线性化 标准卡尔曼滤波 适用于线性化系统,扩展卡尔曼滤波 则扩展到了非线性系统,核心原理就是将非线性系统线性化,主要用的的知识点是 泰勒展开(我另外一篇文章的链接),如下是泰勒展开的公式…...
AI作为学术评审专家有哪些优缺点?
大家好这里是AIWritePaper官方账号,官网👉AIWritePaper论文完成初稿之后,一般情况下,宝子们还需要找专家给我们提出评审意见。找专家评审其实并不容易,即使对老师来说,找人评审论文也是一件苦活。我们这个时…...
微信小程序登录和获取手机号
目录 准备工作 实现流程 实现代码 公共部分 通过code获取openid等信息 解密手机号 扩展 不借助工具类实现解密 借助工具类获取access_token 准备工作 需要小程序账号(可以去微信公众平台创建一个测试号或者正式号) appid:小程序id …...
4.Matplotlib:基础绘图
一 直方图 1.如何构建直方图 将值的范围分段,将整个值的范围分成一系列间隔,然后计算每个间隔中有多少值。 2.直方图的适用场景 一般用横轴表示数据类型,纵轴表示分布情况。 直方图可以用于识别数据的分布模式和异常值,以及观察数…...
与Aspose.pdf类似的jar库分享
如果你在寻找类似于 Aspose.PDF 的 JAR 库,这些库通常用于处理 PDF 文档的创建、编辑、转换、合并等功能。以下是一些类似的 Java 库,它们提供 PDF 处理的功能,其中一些是收费的,但也有开源选项: 1. iText (iText PDF…...
VSCode 市场发现恶意扩展正在传播勒索软件!
在VSCode 市场中发现了两个隐藏着勒索软件的恶意扩展。其中一个于去年 10 月出现在微软商店,但很长时间没有引起注意。 这些是扩展ahban.shiba 和 ahban.cychelloworld,目前已从商店中删除。 此外,ahban.cychelloworld 扩展于 2024 年 10 月…...
工作流引擎Flowable介绍及SpringBoot整合使用实例
Flowable简介 Flowable 是一个轻量级的业务流程管理(BPM)和工作流引擎,基于 Activiti 项目发展而来,专注于提供高性能、可扩展的工作流解决方案。它主要用于企业级应用中的流程自动化、任务管理和审批流等场景。 Flowable 的核心…...
K8s证书--运维之最佳选择(K8s Certificate - the best Choice for Operation and Maintenance)
K8s证书--运维之最佳选择 No -Number- 01 一个月速通CKA 为了速通CKA,主要办了两件事情 1. 在官方的Killercoda上,练习CKA的题目。把命令敲熟悉。 // https://killercoda.com/killer-shell-ckad 2. 使用K3s在多台虚拟机上快速搭建了K8s集群&…...
MySQL 8.0.41源码目录深度解析:探索数据库内核的架构蓝图
文章目录 MySQL 8.0.41源码目录深度解析:探索数据库内核的架构蓝图一、MySQL 8.0.41 目录结构总览1.1 安装目录核心子目录1.2 数据目录关键组件 二、核心源码模块剖析2.1 SQL 引擎核心(sql / 目录)2.1.1 核心组件2.1.2 架构亮点 2.2 存储引擎…...
Leaflet.js+leaflet.heat实现热力图
Leaflet热力图 #mermaid-svg-I1zXN0OrNCBGKEWy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-I1zXN0OrNCBGKEWy .error-icon{fill:#552222;}#mermaid-svg-I1zXN0OrNCBGKEWy .error-text{fill:#552222;stroke:#5522…...
通过git文件查看大模型下载链接的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
多源最短路:Floyd算法の暴力美学
多源最短路求解的是图中的任意两个节点之间的最短路。 前文我们已经讲过单源最短路,我们完全可以做n次单源最短路算法,求出任意两节点的最短距离。最快的堆优化版的 dijkstra 算法的时间复杂度为o(m * logm),枚举n次时…...
初教六双机一飞冲天动作要领
初教六双机一飞冲天动作要领 初教六双机“一飞冲天”是典型的垂直爬升特技动作,要求双机以近乎垂直的姿态同步高速爬升,展现飞机的动力性能与编队协同能力。以下是该动作的详细技术解析与执行要点: 一、动作定义与特点 基本形态 双机以相同速…...
qtcore在docker容器中运行
FROM ubuntu # 设置时区环境变量 ENV TZAsia/Shanghai RUN echo "${TZ}" > /etc/timezone \ && ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime \ && apt update \ && apt install -y tzdata \ && rm -rf /var/lib/apt…...
simpleITK - Setup - Pythonic Syntactic Sugar
Pythonic Syntactic Sugar Image Basics Notebook 非常简单,与 ITK 的 C 接口非常接近。 Sugar非常棒,它能让你精力充沛,更快地完成任务!SimpleITK 也应用了大量Sugar来帮助更快地完成任务。 %matplotlib inline import matplo…...
【leetcode hot 100 215】数组中的第K个最大元素
解法一:维护最大最小值 -> 堆 -> k个元素的最小值堆 class Solution {public int findKthLargest(int[] nums, int k) {// 维护最大最小值 -> 堆 -> k个元素的最小值堆PriorityQueue<Integer> heap new PriorityQueue<>((n1, n2) -> n…...
下载vmware17
我用VMware10安装ubuntu24,死活不能成功,要么突然退出,要么装着装着,眼看完成,居然卡住不动,一查日志,提示光盘读取失败(用的ISO文件,居然装模作样的说光驱读取失败&…...
德昂观点:如何看待MicroStrategy改名为Strategy?
2025年2月,纳斯达克上市公司MicroStrategy(股票代码:MSTR)宣布更名为“Strategy”,并同步启用全新品牌标识与橙色主视觉。这不仅是品牌形象的更新,更是公司战略方向的明确宣示。德昂作为MSTR中国区BI合作伙…...
嵌入式八股RTOS与Linux---网络系统篇
前言 关于计网的什么TCP三次握手 几层模型啊TCP报文啥的不在这里讲,会单独分成一个计算机网络模块 这里主要介绍介绍lwip和socket FreeRTOS下的网络接口–移植LWIP 实际上FreeRTOS并不自带网络接口,我们一般会通过移植lwip协议栈让FreeRTOS可以通过网络接口收发数据,具体可…...
Django 生成 ssl 安全证书,切换 https、wss协议(daphne 、nginx)
Django 普通 http 协议不够安全,无法支持连接本地摄像头(虽然在本地 localhost 上能连),此时需要切换成 https 协议(先提个醒,我这个方法最后失败了,不过对您应该也有帮助) 目录 配置…...
告别Win10强制更新:永久关闭系统更新指南
你是否厌倦了Win10在开关机时的强制自动更新?无论你是在赶时间还是专注于工作,那突如其来的更新提示总是让人不胜其烦。屏幕上那句“正在更新,请勿关闭电源”的提示,仿佛是对你无奈的嘲笑。别担心,今天我将教你如何永久…...
【django】2-1 (django配置) 应用配置、中间件配置、模板配置
文章目录 1 基本设置2 应用配置2.1 django核心应用2.2 常用第三方应用 3 中间件3.1 默认使用的中间件3.2 其它内置中间件3.3 第三方中间件3.4 中间件的执行顺序 4 模板引擎配置4.1 配置字典的键4.2 上下文处理器 创建django项目后,会自动生成初始的项目文件如下&…...
