【JVM】垃圾回收机制(Garbage Collection)
目录
一、什么是垃圾回收?
二、为什么要有垃圾回收机制(GC)?
三、垃圾回收主要回收的内存区域
四、死亡对象的判断算法
a)引用计数算法
b)可达性分析算法
五、垃圾回收算法
a)标记-清除算法
b)复制算法
c)标记-整理算法
d)分代算法
六、垃圾回收器
一、什么是垃圾回收?
垃圾回收指的是自动管理和释放不再被程序使用的内存资源的过程。在程序运行过程中,动态分配的内存会被使用,但也需要在不再需要时释放,以免占用过多的内存空间,导致内存泄漏或内存溢出等问题。
二、为什么要有垃圾回收机制(GC)?
早在学习C语言中,有这么一块内容:动态内存管理。动态内存管理的主要内容就是通过 malloc 申请内存,free 释放内存。
- 此处 malloc 申请到的内存,生命周期是跟随整个进程的。
- 这一点对于服务器程序就很不友好了,服务器每个请求都去 malloc 一块内存,如果没有 free 释放,就会使申请的内存越来越多,后续想要申请内存就无法申请了。这就是内存泄漏问题。
而在实际开发中,很容易出现 free 不小心就忘记调用了,或者因为一些情况导致 free 没有被执行到,例如代码块中存在 if 导致的 return 或者 抛出异常了(当前C语言没有异常这一说)。因此,内存泄漏是一个很大的问题。
能否让释放内存的操作,由程序自动负责完成,而不是依赖程序员手动释放呢?
- 此时就引入了垃圾回收机制(GC),来解决上述问题。
三、垃圾回收主要回收的内存区域
JVM 在运行 Java 程序时,将内存划分为不同的区域,称为运行时数据区。这些区域包括方法区、堆、栈(虚拟机栈)、本地方法栈和程序计数器等。程序在执行之前先要把 Java 代码转换成字节码(.class文件),JVM 首先需要把字节码通过一定的方式(类加载器)把文件加载到内存中(即运行时数据区)。
对于程序计数器、虚拟机栈、本地方法栈这三部分区域而言,其生命周期与相关线程有关,随线程而生,随线程而灭。并且这三个区域的内存分配与回收具有确定性,因为当方法结束或者线程结束时,内存就自然跟着线程回收了。
而对于方法区,方法区主要存储的是类加载后的元数据信息(静态变量,常量池等),这些信息在程序运行期间基本上是不会发生变化的。
因此,在Java虚拟机中,垃圾回收主要针对的是 堆 区域进行回收。
前面说到,垃圾回收指的是自动管理和释放不再被程序使用的内存资源的过程,在Java堆中,存放着几乎所有的对象实例,因此内存回收,也可以叫做死亡对象的回收。
垃圾回收器在对堆进行垃圾回收前,首先要判断这些对象哪些还存活,哪些已经“死去”。判断对象是否已“死”有以下几种算法。
四、死亡对象的判断算法
a)引用计数算法
引用计数法的描述如下:
- 引用计数算法是一种简单的垃圾回收算法,它基于对象的引用计数来确定何时可以回收对象。在引用计数算法中,每个对象都会有一个与之关联的引用计数,用来记录有多少个指针指向该对象。当引用计数为0时,表示该对象不再被引用,可以安全地回收。
- 这种算法的实现相对简单,通常在对象创建和销毁时维护引用计数。当有新的指针指向对象时,引用计数加1;当指针不再指向对象时,引用计数减1。当引用计数减到0时,垃圾回收器会立即回收该对象。
引用计数算法的优点是实现简单,且判定效率也比较高,可以及时回收不再使用的对象。比如Python语言就采用引用计数法进行管理内存。
但是,在主流的JVM中没有选用引用计数法来管理内存,最主要的原因就是引用计数法无法解决对象的循环引用问题。即如果两个或多个对象之间存在循环引用,它们的引用计数永远不会为0,即使它们已经不再被程序使用,也无法被回收。这会导致内存泄漏,占用大量的内存空间。
b)可达性分析算法
JVM 就是采用“可达性分析”来判断对象是否存活(同样采用此法的还有C#、Lisp),该算法可以有效处理循环引用问题,其核心思想为:
- 通过一系列称为“GC Roots”的对象作为起始点,从这些节点开始向下搜索(遍历),搜索走过的路径称之为“引用链”,当一个对象到GC Roots没有任何的引用链相连时(从GC Roots到这个对象不可达),证明此对象是不可用的。
- 一旦完成了可达性分析,JVM 就可以安全地回收那些不可达的对象,释放它们所占用的内存空间。
如上图所示,对象Object5-Object7之间虽然彼此还有关联,但是它们到GC Roots是不可达的,因此它们会被判定为可回收对象。
★在Java语言中,可作为GC Roots的对象包含下面几种:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象;
- 方法区中类静态属性引用的对象;
- 方法区中常量引用的对象;
- 本地方法栈中 JNI(Native方法)引用的对象。
通过可达性分析算法,JVM 就能够将死亡对象标记出来了,标记出来之后就要进行垃圾回收操作。在介绍垃圾回收器之前,先介绍垃圾回收器使用的几种算法。
五、垃圾回收算法
a)标记-清除算法
“标记-清除”算法是最基础的垃圾回收算法。算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
后续的回收算法都是基于这种思路,并对其不足加以改进而已。
“标记-清除”算法的不足主要有两个:
- 效率问题:标记和清除这两个过程的效率都不高,特别是在堆中对象数量庞大的情况下。
- 空间问题:标记清除后会产生大量不连续的内存碎片,内存碎片太多可能会导致以后在程序运行中,需要分配较大对象时,无法找到足够连续的内存而导致内存分配失败,或不得不提前触发另一次垃圾回收。
b)复制算法
“复制”算法解决了“标记-清除”算法两个主要问题,即内存碎片化问题和效率问题。
- 它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。
- 当这块内存需要进行垃圾回收时,会将此区域还存活着的对象复制到另一块上面,然后再把已经使用过的内存区域一次清理掉。
这样做的好处就在于不仅解决了“标记-清除”的主要问题,且算法实现简单,运行高效。解决内存碎片化问题主要体现在,复制过程中通过移动堆顶指针,按顺序进行分配,使碎片化内存被复制到连续的一块空间。
不过,复制算法也有一些缺点:例如在一轮GC中,大部分对象都是长期存活的,只有少数对象需要回收,那么复制算法就会造成大量的复制操作,导致影响性能。
c)标记-整理算法
“标记-整理”算法的提出,则是为了解决“复制”算法在对象存活率较高时,会进行比较多的复制操作这样的问题。
- 标记过程仍与“标记-清除”算法的标记过程一致;
- 但后续步骤不是直接对可回收对象进行回收,而是让所有存活对象都向一端移动,以便整理出一块连续的内存空间。这个思想类似于双指针算法,但其移动对象的过程更复杂。
上述过程仍有一些缺点:即移动存活对象的过程会带来较大的开销。
d)分代算法
综合以上三种算法,JVM并没有直接使用其中的一种,而是结合这三种算法,搞出了一个“综合性”方案,即分代算法。
实际上,堆里面分为两个区域:新生代和老生代,新生代放新建的对象,当经过一定 GC 次数之后还存活的对象才放入老生代。新生代还有三个区域:一个 Endn + 两个 Survivor(S0/S1).
分代算法就是通过区域划分,实现不同区域使用不同的的垃圾回收策略,从而实现更好的垃圾回收。
这就好比中国的一国两制方针一样,对于不同的情况和地域设置更符合当地的规则,从而实现更好的管理,这就是分代算法的设计思想。
当前 JVM 垃圾回收都采用的是“分代”算法。在新生代中,每次垃圾回收都有大批的对象死去,只有少量存活,因此采用复制算法;而老年代中对象存活率高、没有额外空间对它进行分配担保,就必须采用“标记-清除”或者“标记-整理”算法。
- 对于新生代来说,98%的对象都是“朝生夕死”的,所以并不需要按照1:1的比例来划分内存空间,而是将新生代内存分为一块比较大的Eden(伊甸园)空间和两块比较小的Survivor(幸存者)空间,每次使用Eden和其中一块Survivor(两个Survivor区域,一个称为From区,一个称为To区)。
- 当回收时,将Eden和Survivor中还存活的对象一次性复制到另一块Survivor上,最后清理掉Eden和刚才使用过的Survivor空间。完成一次对象复制后,From区和To区的角色会互换。
- HotSpot虚拟机默认Eden与Survivor的大小比例是8:1,也就是说Eden:Survivor From:Survivor To = 8:1:1。所以每次新生代可用内存空间为整个新生代容量的90%,而剩下的10%用来存放回收后存活的对象。
哪些对象会进入新生代?哪些对象会进入老年代?
- 新生代:一般新创建的对象都会进入新生代;
- 老年代:大对象和经历了 N 次(一般情况默认是 15 次)垃圾回收依然存活下来的对象会从新生代移动到老年代。
面试题:请问了解 Minor GC 和 Full GC 吗?这两种GC有什么不一样吗?
- Minor GC又称为新生代GC,指的是发生在新生代的垃圾回收。因为新生代中的Java对象大多都具有朝生夕灭的特性,因此Minor GC(采用复制算法)非常频繁,一般回收速度也比较快。
- Full GC又称为老年代GC或者Major GC:指发生在老年代的垃圾回收。出现了Major GC,经常会伴随至少一次的Minor GC(并非绝对)。Major GC的触发频率通常比较低,且速度一般会比Minor GC慢10倍以上。
六、垃圾回收器
如果说上面所讲的垃圾回收算法是内存回收的方法论,那么垃圾回收器就是内存回收的具体实现。
垃圾回收器的作用:垃圾回收器是为了保证程序能够正常、持久运行的一种技术,它是将程序中的死亡对象,也就是垃圾对象进行清除,从而保证了新对象能够正常申请到内存空间。
以下这些回收器是 HotSpot 虚拟机随着不同版本推出的重要的垃圾回收器:
上图展示了7种作用于不同分代的垃圾回收器,如果两个回收器之间存在连线,就说明它们之间可以搭配使用。所处的区域,表示它是属于新生代回收器还是老年代回收器。
为什么会有这么多垃圾回收器?
- 其主要原因是:自从有了 Java 语言就有了垃圾回收器,这么多垃圾回收器其实是历史发展的产物。随着时间的推移和技术的进步,人们对垃圾回收器的性能、吞吐量、停顿时间等方面提出了更高的要求,因此就产生了更多更新的垃圾回收器。
此处就不展开介绍每种垃圾回收器了。
相关文章:

【JVM】垃圾回收机制(Garbage Collection)
目录 一、什么是垃圾回收? 二、为什么要有垃圾回收机制(GC)? 三、垃圾回收主要回收的内存区域 四、死亡对象的判断算法 a)引用计数算法 b)可达性分析算法 五、垃圾回收算法 a)标记-清除…...
C++中的priority_queue模拟实现
目录 priority_queue模拟实现 priority_queue类定义 priority_queue构造函数 priority_queue类push()函数 priority_queue类pop()函数 priority_queue类size()函数 priority_queue类empty()函数 priority_queue类top()函数 仿函数与priority_queue类模拟实现 仿函数 …...
【Kafka】1.Kafka核心概念、应用场景、常见问题及异常
Kafka 是一个分布式流处理平台,最初由 LinkedIn 开发,后成为 Apache 软件基金会的顶级项目。 它主要用于构建实时数据管道和流式应用程序。它能够高效地处理高吞吐量的数据,并支持消息发布和订阅模型。Kafka 的主要用途包括实时分析、事件源、…...
LTE的EARFCN和band之间的对应关系
一、通过EARFCN查询对应band 工作中经常遇到只知道EARFCN而需要计算band的情况,因此查了相关协议,找到了他们之间的对应关系,可以直接查表,非常方便。 具体见: 3GPP TS 36.101 5.7.3 Carrier frequency and EAR…...

解决问题:Docker证书到期(Error grabbing logs: rpc error: code = Unknown)导致无法查看日志
问题描述 Docker查看日志时portainer报错信息如下: Error grabbing logs: rpc error: code Unknown desc warning: incomplete log stream. some logs could not be retrieved for the following reasons: node klf9fdsjjt5tb0w4hxgr4s231 is not available报错…...
【C语言】预处理器
我们在开始编写一份程序的时候,从键盘录入的第一行代码: #include <stdio.h>这里就使用了预处理,引入头文件。 C预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C预处理器只不过是一…...
QtConcurrent::run操作界面ui的注意事项(2)
前面的“QtConcurrent::run操作界面ui的注意事项(1)”,末尾说了跨线程的问题,引出了Qt千好万好,就是跨线程不好。下面是认为的最简单的解决办法:使用QMetaObject::invokeMethod(相比较信号-槽&a…...

黑马程序员HarmonyOS4+NEXT星河版入门到企业级实战教程笔记
HarmonyOS NEXT是纯血鸿蒙,鸿蒙原生应用,彻底摆脱安卓 本课程是基于harmony os4的,与next仅部分api有区别 套件 语言&框架 harmony os design ArkTs 语言 ArkUI 提供各种组件 ArkCompiler 方舟编译器 开发&测试 DevEco Studio 开发…...

嵌入式全栈开发学习笔记---C语言笔试复习大全13(编程题9~16)
目录 9.查找字符数组中字符位置(输入hello e 输出2); 10、查找字符数组中字符串的位置(输入hello ll 输出3); 11、字符数组中在指定位置插入字符;(输入hello 3 a 输出heallo…...

https网站安全证书的作用与免费申请办法
HTTPS网站安全证书,也称为SSL证书,网站通过申请SSL证书将http协议升级到https协议 HTTPS网站安全证书的作用 1 增强用户信任:未使用https协议的网站,用户访问时浏览器会有“不安全”弹窗提示 2 提升SEO排名:搜索引擎…...

自动化测试再升级,大模型与软件测试相结合
近年来,软件行业一直在迅速发展,为了保证软件质量和提高效率,软件测试领域也在不断演进。如今,大模型技术的崛起为软件测试带来了前所未有的智能化浪潮。 软件测试一直是确保软件质量的关键环节,但传统的手动测试方法存…...
centos7 基础命令
一、基础信息: 查看IP地址: ip add 重启网络服务: service network restart 查看网卡配置: cat /etc/sysconfig/network-scripts/ifcfg-ens33 启动网卡: ifup ens33 查看内存: free -m 查看CPU: cat /proc/cpuin…...
【设计模式】之单例模式
系列文章目录 【设计模式】之责任链模式【设计模式】之策略模式【设计模式】之模板方法模式 文章目录 系列文章目录 前言 一、什么是单例模式 二、如何使用单例模式 1.单线程使用 2.多线程使用(一) 3.多线程使用(二) 4.多线程使用…...

3d模型实体显示有隐藏黑线?---模大狮模型网
在3D建模和设计领域,细节决定成败。然而,在处理3D模型时,可能会遇到模型实体上出现隐藏黑线的问题。这些黑线可能影响模型的视觉质量和呈现效果。因此,了解并解决这些隐藏黑线的问题至关重要。本文将探讨隐藏黑线出现的原因&#…...

共享购:全新消费模式的探索与实践
在消费模式日益创新的今天,共享购模式以其独特的消费与收益双重机制,吸引了众多消费者的目光。这一模式不仅为消费者带来了全新的购物体验,也为商家和平台带来了可观的收益。 一、会员体系:共享购的基石 在共享购模式下ÿ…...

Java集合 总结篇(全)
Java集合 集合底层框架总结 List 代表的有序,可重复的集合。 ArrayList -- 数组 -- 把他想象成C中的Vector就可以,当数组空间不够的时候,会自动扩容。 -- 线程不安全 LinkedList -- 双向链表 -- 可以将他理解成一个链表,不支持…...
Dubbo分层架构深度解析
引言 Dubbo作为一款备受欢迎的高性能、轻量级的Java RPC框架,在现代分布式系统中扮演着至关重要的角色。随着互联网行业的快速发展,服务间的通信变得越来越频繁,这也使得对于高效、可靠的远程通信方案的需求变得愈发迫切。在这样的背景下&am…...
LocalDate 数据库不兼容问题,因为LocalDate 是 long 类型的
我今天遇到一报错: SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession316f9272] was not registered for synchronization because synchronization is not active JDBC Connection [HikariProxyConnection2127597288 wrapping com.mysql.cj.jdbc…...

RVM(相关向量机)、CNN_RVM(卷积神经网络结合相关向量机)、RVM-Adaboost(相关向量机结合Adaboost)
当我们谈到RVM(Relevance Vector Machine,相关向量机)、CNN_RVM(卷积神经网络结合相关向量机)以及RVM-Adaboost(相关向量机结合AdaBoost算法)时,每种模型都有其独特的原理和结构。以…...

Java--方法的使用
1.1什么是方法 方法顾名思义就是解决问题的办法,在程序员写代码的时候,会遇到很多逻辑结构一样,解决相同问题时,每次都写一样的代码,这会使代码看起来比较绒余,代码量也比较多,为了解决这个问题…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...