2023.9.2 关于 JVM 垃圾回收机制(GC)

目录

为什么要有垃圾回收机制?

STW(Stop The World)问题

垃圾回收机制主要回收哪个内存区域?

垃圾对象判断算法

引用计数算法

可达性分析算法

垃圾对象回收算法

标记清除算法

复制算法

标记整理算法

分代算法


为什么要有垃圾回收机制?

  • 自动内存管理:垃圾回收机制使得内存的分配释放过程自动化,开发者不需要手动跟踪和释放不再使用的内存,减轻了开发工作量
  • 避免内存泄漏:内存泄漏指程序中分配的内存空间无法被回收和重用,导致内存资源的浪费和耗尽,而垃圾回收机制可以自动检测和回收这些不再使用的内存,从而避免内存泄漏
  • 解决内存碎片化:内存碎片化指内存空间的可用部分被分割成多个小块,无法满足大块内存的分配请求,垃圾回收机制可以通过整理和压缩内存空间,将分散的小块内存合并成更大的可用内存块,从而减少了内存碎片化问题
  • 提高程序性能:垃圾回收机制虽然会引入额外的性能开销,但相比手动内存管理,它通过智能算法来判断哪些对象是可回收的,从而避免了不必要的内存分配和释放操作,可以更高效的管理内存资源,从而提高程序的整体性能
  • 内存安全:垃圾回收机制可以检测和处理悬空引用和野指针等内存安全问题,它可以识别不再被引用的对象,并再必要时进行回收,避免了程序访问无效内存的风险

STW(Stop The World)问题

垃圾回收机制最大的问题就是会引入额外的 空间+时间 开销

  • 空间上:额外消耗 CPU 和内存资源
  • 时间上:STW 问题

STW 问题 指程序运行到需要用 GC 释放内存的时候,可能会导致程序的响应变慢,反应到用户便可能存在明显的卡顿


总结:

总体来说,JVM 垃圾回收机制是 Java 语言的重要特性,它为开发者提供了方便、安全、高效的内存管理方式,减少了内存相关的错误和问题,其开发效率是大于运行效率的!

垃圾回收机制主要回收哪个内存区域?

  • GC 主要是针对 进行释放回收
  • GC 以 对象为基本单位 进行回收

垃圾对象判断算法

引用计数算法

  • 引用计数算法被 Python、PHP 所采用,非 Java 所采用的算法

具体思路:

  • 每个对象都有一个关联的计数器,用于记录当前对象被其他对象引用的次数
  • 每多一个引用指向该对象,计数器就 +1
  • 每少一个引用指向该对象,计数器就 -1
  • 当对象的计数器为 0 时,将被视为垃圾对象,可被垃圾回收器回收 

缺点:

  • 内存空间利用率低:对于小对象来说,可能一个计数器的所占内存比其本身还大
  • 存在循环引用的问题


可达性分析算法

  • 可达性分析算法为 Java 所采用的垃圾对象​​​​判断算法

具体思路:

  • 根集确定(GC Roots):垃圾回收器首先要确定根集的内容,其根集可为 栈中引用的对象方法区中类静态属性引用对象方法区中常量引用的对象本地方法栈中 Native 方法引用的对象

  • 根集遍历:从根集中的每个对象开始,通过对象之间的引用关系,递归地遍历对象图。遍历过程中,将访问到的对象标记为"可达"

  • 标记阶段:标记阶段是遍历过程中的核心步骤,通过对每个对象进行标记,将其标记为可达或不可达。已经标记为可达的对象说明它们仍然被根集或其他可达对象引用,而未标记的对象则被判定为垃圾对象

  • 清除阶段:在标记阶段完成后,垃圾回收器会遍历整个堆内存,将未标记的对象进行清除,释放其占用的内存空间。清除后的内存空间可以被重新利用

优点:

  • 解决循环引用:通过从根集出发,仅标记可达的对象,不可达的对象将被判断为垃圾,即使存在循环引用也能正确回收
  • 高效性:可达性分析算法的效率较高,它只对可达对象进行标记,不需要扫描整个堆内存

垃圾对象回收算法

标记清除算法

基本步骤:

  • 标记阶段:通过可达性分析算法,将可达的对象进行标记,未标记的对象则被标记为垃圾
  • 清除阶段:垃圾回收器遍历整整个堆内存,将未标记的对象进行清除,清除后的内存空间可以被重新利用

缺点:

  • 内存碎片化:标记清除算法会在清除阶段产生内存碎片,即被标记未垃圾袋对象所占用的内存空间,从而导致被释放的空闲空间是零散的不是连续的,可能会导致申请大一点连续内存空间的时候申请失败!
  • 垃圾回收的停顿时间:在标记和清除过程中,垃圾回收器需要暂停应用程序的执行。这种停顿时间可能导致应用程序的响应性能下降,特别是当堆内存较大且垃圾对象较多时


复制算法

  • 针对内存碎片问题,引入的算法

基本步骤:

  • 标记阶段:通过可达性分析算法,将所有可达对象进行标记
  • 复制阶段:在复制阶段,垃圾回收器将标记对象从 From区 复制到 To区 复制过程中,对象的存储地址发送变化,即对象被移动到 To 区
  • 更新引用阶段:完成复制阶段后,需要更新所有指向被复制对象的引用,使其指向对象在 To区的新地址
  • 交换空间:完成引用更新后,From区 和 To区 的角色互换,这样下一次的垃圾回收操作将在新的 To区 进行

缺点:

  • 内存开销:复制算法需要将存活对象复制到 To区,因此需要额外的内存空间来存放复制的对象,从而会增加内存的开销,尤其当存活对象较多时
  • 复制操作的时间开销:复制算法需要将存活对象复制到 To区,这涉及对象的拷贝操作,可能会增加垃圾回收的时间开销。

标记整理算法

  • 针对复制算法内存开销大,引入的算法

基本步骤:

  • 标记阶段:通过可达性分析算法,将所有可达对象进行标记

  • 整理拷贝阶段:垃圾回收器从堆的起始位置开始,依次复制所有活动的对象到堆的另一端,并按顺序排列。拷贝过程中,对象的存储地址发生变化

  • 整理更新引用关系阶段:在拷贝阶段中,垃圾回收器会更新所有指向被复制对象的引用,使其指向对象在新位置的地址。​​​​​

  • 更新根集:在整理阶段完成后,垃圾回收器需要更新根集中的引用,使其指向对象在新位置的地址

  • 空间回收:整理阶段完成后,垃圾回收器可以释放整理前的内存空间,从而减少内存碎片

缺点:

  • 整理过程的时间开销:标记整理算法需要将存活对象整理并移动,这可能涉及对象的拷贝和引用更新操作,增加了垃圾回收的时间开销

  • 停顿时间:在整理阶段,垃圾回收器需要暂停应用程序的执行。这种停顿时间可能影响应用程序的响应性能,特别是当堆内存较大且存活对象较多时


分代算法

  • 总和上述三种算法,通过区域划分,实现不同区域使用不同的垃圾回收算法,从而提高垃圾回收的总体效率

经验规律:

  • 大部分对象在其生命周期中熬不过一轮 GC,即很快成为垃圾,而被回收
  • 一个对象能经过多轮 GC 而不被回收,说明该对象大概率还会长时间的继续存在下去

算法解释: 

新生代:

新生代用于存放新创建的对象。通常采用 复制算法 作为垃圾回收策略。新生代被划分为两个区域:伊甸区和两个生存区。新创建的对象首先分配在伊甸区,当伊甸区满时,仍然存活的对象将被复制到一个生存区,然后在两个生存区之间进行复制和清理。经过多次复制后仍然存活的对象会被晋升到老年代

老年代:

老年代用于存放存活时间较长的对象。由于老年代的对象存活时间更长,GC 的频率相对较低,因此采用 标记整理算法。老年代的垃圾回收相对较少频繁,因为大多数对象在新生代就被回收了

优点:

  • 针对对象生命周期的优化:分代算法通过针对不同代的不同垃圾回收策略,针对对象的生命周期进行优化。新生代采用复制算法,可以迅速回收大部分短命对象,而老年代采用更成熟的垃圾回收算法,适应长寿命对象的特点。

  • 减少垃圾回收的范围:由于大部分对象很快就变得不可达,将堆内存划分为代可以将垃圾回收的范围缩小到新生代,从而减少了垃圾回收的开销。

  • 提高垃圾回收的效率:通过根据对象生命周期的特点采用不同的垃圾回收策略,分代算法可以提高垃圾回收的效率。新生代采用复制算法,具有高效的回收速度,而老年代采用更成熟的算法,可以更好地处理长寿命对象。

注意:若新创建的对象非常大,则直接进入老年代,因为一个大对象进行复制算法,其开销比较大,而且因为它是一个大对象,费很大的开销所创建出来的,很大可能是不会立即销毁的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/66579.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Navicat16连接Oracle报错:Oracle library is not loaded

1、有时候我们在用navicat的时候连接oracle的时候,它会提示我们Oracle library is not loaded,这时候我们要首先验证本机上是否已安装oracle的客户端,如果已安装客户段,navicat中的oci.dll选择我们安装的客户段的oci.dll文件 2、…

MATLAB中编译器中的变量联系到Simulink

MATLAB中编译器中的变量联系到Simulink 现在编译器中创建变量,进行编译,使其生成在工作区。 然后在Simulink中国使用变量即可。

opencv入门-Opencv原理以及Opencv-Python安装

图像的表示 1,位数 计算机采用0/1编码的系统,数字图像也是0/1来记录信息,图像都是8位数图像,包含0~255灰度, 其中0代表最黑,1代表最白 3, 4,OpenCV部署方法 安装OpenCV之前…

Hadoop 集群小文件归档 HAR、小文件优化 Uber 模式

文章目录 小文件归档 HAR小文件优化 Uber 模式 小文件归档 HAR 小文件归档是指将大量小文件合并成较大的文件,从而减少存储开销、元数据管理的开销以及处理时的任务调度开销。 这里我们通过 Hadoop Archive (HAR) 来进行实现,它是一种归档格式&#xf…

使用Docker配置深度学习的运行环境

文章目录 推荐实验环境前言docker安装docker操作docker配置常见方法(安装包、联网、程序管理器)安装驱动的前提要求传统方法安装驱动程序程序管理器安装联网安装deb包安装 安装完成后的设置非传统方法安装-通过容器安装驱动的前提要求安装NVIDIA-Contain…

Scala集合继承体系图

Scala集合简介 1) Scala 的集合有三大类:序列 Seq、集Set、映射 Map,所有的集合都扩展自 Iterable特质。 2) 对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两个包 不可变集合…

Orangepi安装外设库 wiringPi

注意:mobaXterm传送文件要在SSH登陆环境下才可以。 同时电脑和orangepi都在同一个wifi下。

浅谈React split_分割字符串

当我们需要将一个字符串按照指定的分隔符进行分割成数组时,可以使用JavaScript中的split方法。在React中,我们可以在组件的生命周期方法中使用split方法来实现这个功能。 下面是一个使用split方法的示例代码,并对其进行详细解释:…

unittest框架的使用

先简单介绍一下unittest的核心组成部分: 测试夹具:Test Fixture 一般用于执行测试用例的准备或者清理工作,比如测试开始前的数据准备或者测试结束的数据清理等。通过setUp()、tearDown()、setUpClass()、tearDownClass()这四个钩子函数实现了…

javaee 事务 事务的特性 事务的并发问题 事务的隔离级别

什么是事务(Transaction) 是并发控制的单元,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,sql 能将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性。事务…

int num = 0; while(true) { num++; if (num == 3) { System.out.println(3); } }

昨天看到一篇帖子,以下代码的运行结果是什么呢? int num 0; while(true) {num;if (num 3) {System.out.println(3);} }答案是无数个3,因为i超过int最大值会溢出,再从int最小值开始加 但是看到评论里以下代码的运行时间&#x…

tableau基础学习2:时间序列数据预处理与绘图

文章目录 数据预处理1. 原始数据2. 合并数据集2. 创建计算字段 绘图分析1. 趋势分析2. 计算字段趋势分析 这一部分,我们记录一些分析时序趋势的分析步骤 数据预处理 1. 原始数据 原始数据是excel表格,其中包含三个Sheet页, 这里我们选择两…

ModaHub魔搭社区专访百度智能云李莅:以后所有的数据库它都会原生地支持用向量?

ModaHub魔搭社区:您是否认为,以后所有的数据库它都会原生地支持用向量? 李莅:传统数据库广义上也分好几类:一类是关系型的,一类是 NoSQL 类的,还有一类是分析型的数据库。我觉得关系型的这种数据…

Super Resolve Dynamic Scene from Continuous Spike Streams论文笔记

摘要 近期,脉冲相机在记录高动态场景中展示了其优越的潜力。不像传统相机将一个曝光时间内的视觉信息进行压缩成像,脉冲相机连续地输出二的脉冲流来记录动态场景,因此拥有极高的时间分辨率。而现有的脉冲相机重建方法主要集中在重建和脉冲相…

Nginx 和 网关的关系是什么

分析&回答 Nginx也可以实现网关,可以实现对api接口的拦截,负载均衡、反向代理、请求过滤等。网关功能可以进行扩展,比如:安全控制,统一异常处理,XXS,SQL注入等;权限控制,黑白名…

iframe通过postMessage进行跨域通信以及在Angular中使用

写在前面 在前端开发过程中,会遇到一些需要使用iframe的场景,使用iframe关键的一个点是数据之间的传输,基于同源的要求十分苛刻,大家基本上是都是跨域的,如果跨域进行数据传输呢? 大家使用的比较多的就是p…

服务器监控可视化

IT监控可视化是一种将IT监控数据以图形化的方式呈现给用户的技术,可以帮助用户更直观、更易懂地了解IT系统的运行状况。服务器监控可视化是其中的一个重要应用场景,可以将服务器的各种性能指标以图表、仪表盘等形式展示,以便管理员更好地了解…

数据结构学习系列之顺序表的查找与排序以及去重

顺序表的查找&#xff1a;根据顺序表中数据元素的位置进行查找&#xff0c;代码如下&#xff1a;示例代码&#xff1a; int search_seq_list(list_t *seq_list,int pos,int *num){if(NULL seq_list || NULL num){printf("内存分配失败\n");return -1;}if( pos <…

c++ set/multiset

set/multiset 集合&#xff0c;一个单个&#xff0c;一个多个(multi)。两个库都是"set"。 https://blog.csdn.net/fckbb/article/details/130917681 对象创建 set(const Pred& compPred()&#xff0c;const A& alA()):创建空集合。set(const set& x):…

HTTP协议初识·中篇

加上目录&#xff0c;会出现导向不正确的情况&#xff0c;可能是bug&#xff0c;目录一长就容易出错&#xff1f; 本篇主要讲解了&#xff1a; 网页分离(网页代码和.c文件分离) html链接跳转 网页添加图片 确认并返回资源类型 填写正文长度属性 添加表单 临时重定向 补充知识&a…