当前位置: 首页 > article >正文

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();}
}

按照引用计数算法的逻辑:

  • objAobjB 互相引用,导致它们的引用计数始终不为 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 包含哪些对象?

  1. 栈上的局部变量(方法内的变量)。

  2. 静态变量(属于类的静态字段)。

  3. 运行时常量池中的引用(比如字符串常量池 String Table)。

  4. 本地方法栈 JNI 引用(Native 代码引用的对象)。

  5. 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. 结论

  1. JVM 不使用引用计数算法的主要原因是:无法解决循环引用问题。

  2. JVM 采用可达性分析算法,通过 GC Roots 遍历对象引用链来判断对象是否存活。

  3. JVM 引入四种引用类型,以增强垃圾回收的控制能力,适应不同场景需求。

JVM 的 GC 机制不断优化,比如 G1、ZGC 采用了更先进的垃圾回收策略,使得 Java 的内存管理更高效。

相关文章:

JVM 为什么不使用引用计数算法?——深入解析 GC 策略

在 Java 中&#xff0c;垃圾回收&#xff08;Garbage Collection, GC&#xff09;是一个至关重要的功能&#xff0c;它能够自动管理内存&#xff0c;回收不再使用的对象&#xff0c;从而防止内存泄漏。然而&#xff0c;在垃圾回收的实现上&#xff0c;JVM 并未采用引用计数算法…...

【HarmonyOS NEXT】EventHub和Emitter的使用场景与区别

一、EventHub是什么&#xff1f; 移动应用开发的同学应该比较了解EventHub&#xff0c;类似于EventBus。标准的事件广播通知&#xff0c;订阅&#xff0c;取消订阅的处理。EventHub模块提供了事件中心&#xff0c;提供订阅、取消订阅、触发事件的能力。 类似的框架工具有很多…...

01-系统编程

一、程序和进程的区别&#xff1a; window系统&#xff1a; 1、程序存储在硬盘中&#xff0c;文件格式为.exe后缀&#xff0c;静态的 2、进程运行在内存中&#xff0c;动态的 Linux系统 1、程序存储在硬盘中&#xff0c;文件格式为.ELF&#xff08;可执行的链接文件&#…...

Linux编译器gcc/g++使用完全指南:从编译原理到动静态链接

一、gcc/g基础认知 在Linux开发环境中&#xff0c;gcc和g是我们最常用的编译器工具&#xff1a; gcc&#xff1a;GNU C Compiler&#xff0c;专门用于编译C语言程序g&#xff1a;GNU C Compiler&#xff0c;用于编译C程序&#xff08;也可编译C语言&#xff09; &#x1f4cc…...

UMI-OCR Docker 部署

额外补充 Docker 0.前置条件 部署前&#xff0c;请检查主机的CPU是否具有AVX指令集 lscpu | grep avx 输出如下即可继续部署 Flags: ... avx ... avx2 ... 1.下载dockerfile wget https://raw.githubusercontent.com/hiroi-sora/Umi-OCR_runtime_linux/main/Do…...

26考研|数学分析:定积分及应用

这一部分作为数学分析的灵魂&#xff0c;在数学分析的计算中&#xff0c;绝大部分的问题都可以转换成定积分的计算问题&#xff0c;所以在这部分的学习中&#xff0c;一定要注意提升计算能力&#xff0c;除此之外&#xff0c;由积分引出的相关积分不等式也是分析的重点和难点&a…...

React Hooks使用方法:useState,useRef,useEffect,useReducer,useContext用法实战案例

react hooks介绍&#xff0c;包括了state&#xff0c;ref&#xff0c;effect&#xff0c;reducer&#xff0c;context等常见hooks&#xff0c;也包括forwardRef和createContext用法&#xff0c;下面看代码吧&#xff0c;我用的是js写的。每个hook都做了个案例。 // 使用state来…...

线程池详解:在SpringBoot中的最佳实践

线程池详解&#xff1a;在SpringBoot中的最佳实践 引言 在Java并发编程中&#xff0c;线程池是一种非常重要的资源管理工具&#xff0c;它允许我们在应用程序中有效地管理和重用线程&#xff0c;从而提高性能并降低资源消耗。特别是在SpringBoot等企业级应用中&#xff0c;正…...

扩展卡尔曼滤波

1.非线性系统的线性化 标准卡尔曼滤波 适用于线性化系统&#xff0c;扩展卡尔曼滤波 则扩展到了非线性系统&#xff0c;核心原理就是将非线性系统线性化&#xff0c;主要用的的知识点是 泰勒展开&#xff08;我另外一篇文章的链接&#xff09;&#xff0c;如下是泰勒展开的公式…...

AI作为学术评审专家有哪些优缺点?

大家好这里是AIWritePaper官方账号&#xff0c;官网&#x1f449;AIWritePaper论文完成初稿之后&#xff0c;一般情况下&#xff0c;宝子们还需要找专家给我们提出评审意见。找专家评审其实并不容易&#xff0c;即使对老师来说&#xff0c;找人评审论文也是一件苦活。我们这个时…...

微信小程序登录和获取手机号

目录 准备工作 实现流程 实现代码 公共部分 通过code获取openid等信息 解密手机号 扩展 不借助工具类实现解密 借助工具类获取access_token 准备工作 需要小程序账号&#xff08;可以去微信公众平台创建一个测试号或者正式号&#xff09; appid&#xff1a;小程序id …...

4.Matplotlib:基础绘图

一 直方图 1.如何构建直方图 将值的范围分段&#xff0c;将整个值的范围分成一系列间隔&#xff0c;然后计算每个间隔中有多少值。 2.直方图的适用场景 一般用横轴表示数据类型&#xff0c;纵轴表示分布情况。 直方图可以用于识别数据的分布模式和异常值&#xff0c;以及观察数…...

与Aspose.pdf类似的jar库分享

如果你在寻找类似于 Aspose.PDF 的 JAR 库&#xff0c;这些库通常用于处理 PDF 文档的创建、编辑、转换、合并等功能。以下是一些类似的 Java 库&#xff0c;它们提供 PDF 处理的功能&#xff0c;其中一些是收费的&#xff0c;但也有开源选项&#xff1a; 1. iText (iText PDF…...

VSCode 市场发现恶意扩展正在传播勒索软件!

在VSCode 市场中发现了两个隐藏着勒索软件的恶意扩展。其中一个于去年 10 月出现在微软商店&#xff0c;但很长时间没有引起注意。 这些是扩展ahban.shiba 和 ahban.cychelloworld&#xff0c;目前已从商店中删除。 此外&#xff0c;ahban.cychelloworld 扩展于 2024 年 10 月…...

工作流引擎Flowable介绍及SpringBoot整合使用实例

Flowable简介 Flowable 是一个轻量级的业务流程管理&#xff08;BPM&#xff09;和工作流引擎&#xff0c;基于 Activiti 项目发展而来&#xff0c;专注于提供高性能、可扩展的工作流解决方案。它主要用于企业级应用中的流程自动化、任务管理和审批流等场景。 Flowable 的核心…...

K8s证书--运维之最佳选择(K8s Certificate - the best Choice for Operation and Maintenance)

K8s证书--运维之最佳选择 No -Number- 01 一个月速通CKA 为了速通CKA&#xff0c;主要办了两件事情 1. 在官方的Killercoda上&#xff0c;练习CKA的题目。把命令敲熟悉。 // https://killercoda.com/killer-shell-ckad 2. 使用K3s在多台虚拟机上快速搭建了K8s集群&…...

MySQL 8.0.41源码目录深度解析:探索数据库内核的架构蓝图

文章目录 MySQL 8.0.41源码目录深度解析&#xff1a;探索数据库内核的架构蓝图一、MySQL 8.0.41 目录结构总览1.1 安装目录核心子目录1.2 数据目录关键组件 二、核心源码模块剖析2.1 SQL 引擎核心&#xff08;sql / 目录&#xff09;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算法の暴力美学

多源最短路求解的是图中的任意两个节点之间的最短路。 前文我们已经讲过单源最短路&#xff0c;我们完全可以做n次单源最短路算法&#xff0c;求出任意两节点的最短距离。最快的堆优化版的 dijkstra 算法的时间复杂度为o&#xff08;m * logm&#xff09;&#xff0c;枚举n次时…...

初教六双机一飞冲天动作要领

初教六双机一飞冲天动作要领 初教六双机“一飞冲天”是典型的垂直爬升特技动作&#xff0c;要求双机以近乎垂直的姿态同步高速爬升&#xff0c;展现飞机的动力性能与编队协同能力。以下是该动作的详细技术解析与执行要点&#xff1a; 一、动作定义与特点 基本形态 双机以相同速…...

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 非常简单&#xff0c;与 ITK 的 C 接口非常接近。 Sugar非常棒&#xff0c;它能让你精力充沛&#xff0c;更快地完成任务&#xff01;SimpleITK 也应用了大量Sugar来帮助更快地完成任务。 %matplotlib inline import matplo…...

【leetcode hot 100 215】数组中的第K个最大元素

解法一&#xff1a;维护最大最小值 -> 堆 -> k个元素的最小值堆 class Solution {public int findKthLargest(int[] nums, int k) {// 维护最大最小值 -> 堆 -> k个元素的最小值堆PriorityQueue<Integer> heap new PriorityQueue<>((n1, n2) -> n…...

下载vmware17

我用VMware10安装ubuntu24&#xff0c;死活不能成功&#xff0c;要么突然退出&#xff0c;要么装着装着&#xff0c;眼看完成&#xff0c;居然卡住不动&#xff0c;一查日志&#xff0c;提示光盘读取失败&#xff08;用的ISO文件&#xff0c;居然装模作样的说光驱读取失败&…...

德昂观点:如何看待MicroStrategy改名为Strategy?

2025年2月&#xff0c;纳斯达克上市公司MicroStrategy&#xff08;股票代码&#xff1a;MSTR&#xff09;宣布更名为“Strategy”&#xff0c;并同步启用全新品牌标识与橙色主视觉。这不仅是品牌形象的更新&#xff0c;更是公司战略方向的明确宣示。德昂作为MSTR中国区BI合作伙…...

嵌入式八股RTOS与Linux---网络系统篇

前言 关于计网的什么TCP三次握手 几层模型啊TCP报文啥的不在这里讲,会单独分成一个计算机网络模块   这里主要介绍介绍lwip和socket FreeRTOS下的网络接口–移植LWIP 实际上FreeRTOS并不自带网络接口,我们一般会通过移植lwip协议栈让FreeRTOS可以通过网络接口收发数据,具体可…...

Django 生成 ssl 安全证书,切换 https、wss协议(daphne 、nginx)

Django 普通 http 协议不够安全&#xff0c;无法支持连接本地摄像头&#xff08;虽然在本地 localhost 上能连&#xff09;&#xff0c;此时需要切换成 https 协议&#xff08;先提个醒&#xff0c;我这个方法最后失败了&#xff0c;不过对您应该也有帮助&#xff09; 目录 配置…...

告别Win10强制更新:永久关闭系统更新指南

你是否厌倦了Win10在开关机时的强制自动更新&#xff1f;无论你是在赶时间还是专注于工作&#xff0c;那突如其来的更新提示总是让人不胜其烦。屏幕上那句“正在更新&#xff0c;请勿关闭电源”的提示&#xff0c;仿佛是对你无奈的嘲笑。别担心&#xff0c;今天我将教你如何永久…...

【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项目后&#xff0c;会自动生成初始的项目文件如下&…...