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

news2025/1/24 14:36:30

目录

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

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.coloradmin.cn/o/965630.html

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

相关文章

thinkphp中使用Elasticsearch 7.0进行多表的搜索

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、thinkphp中使用Elasticsearch 7.0进行多表的搜索二、使用步骤1.引入库2.读入数据 总结 前言 提示:thinkphp中使用Elasticsearch 7.0进行多表的…

stable diffusion实践操作-批次出图

系列文章目录 stable diffusion实践操作 文章目录 系列文章目录前言一、批次出图介绍1.1 webUI设置1.2 参数介绍 二、批次出图使用2.1 如何设置2.1 效果展示 总结 前言 本章主要介绍SD批次出图。 想要一次产生多张图片的时候使用。 一、批次出图介绍 1.1 webUI设置 1.2 参数…

[管理与领导-65]:IT基层管理者 - 辅助技能 - 4- 乌卡时代(VUCA )

前言: 大多数IT人,很勤奋,但都没有职业规划,被工作驱动着前行,然而,作为管理者,你就不能没有职业规划思维,因为你代表一个团队,你的思维决定了一个团队的思维。本文探讨…

2023-9-2 染色法判定二分图

题目链接&#xff1a;染色法判定二分图 #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 100010l, M 200010;int n, m; int h[N], e[M], ne[M], idx;int color[N];void add(int a, int b) {e[idx] b, ne[id…

CSS中border-radius的来美化table的实战方案

border-radius是一种CSS属性&#xff0c;用于设置元素的边框的圆角程度。其具体的用法如下&#xff1a; 设置一个值&#xff1a;可以为元素设置一个单一的圆角半径&#xff0c;这个半径将应用于元素的四个角。例如&#xff1a; div {border-radius: 10px; }设置四个值&#x…

vue Cesium接入在线地图

Cesium接入在线地图只需在创建时将imageryProvider属性换为在线地图的地址即可。 目录 天地图 OSM地图 ArcGIS 地图 谷歌影像地图 天地图 //矢量服务let imageryProvider new Cesium.WebMapTileServiceImageryProvider({url: "http://t0.tianditu.com/vec_w/wmts?s…

创建性-构造者设计模式

前言 我们在使用Retrofit等这些第三方框架的时候&#xff0c;发现他们的使用都很方便&#xff0c;比如Retrofit retrofit new Retrofit.Builder().build()&#xff0c;和我们通常直接new一个对象不同&#xff0c;他是交给Builder类&#xff0c;通过build()函数来构造一个Retro…

解决Ubuntu 或Debian apt-get IPv6问题:如何设置仅使用IPv4

文章目录 解决Ubuntu 或Debian apt-get IPv6问题&#xff1a;如何设置仅使用IPv4 解决Ubuntu 或Debian apt-get IPv6问题&#xff1a;如何设置仅使用IPv4 背景&#xff1a; 在Ubuntu 22.04(包括 20.04 18.04 等版本) 或 Debian (10、11、12)系统中&#xff0c;当你使用apt up…

JS中的new操作符

文章目录 JS中的new操作符一、什么是new&#xff1f;二、new经历了什么过程&#xff1f;三、new的过程分析四、总结 JS中的new操作符 参考&#xff1a;https://www.cnblogs.com/buildnewhomeland/p/12797537.html 一、什么是new&#xff1f; 在JS中&#xff0c;new的作用是通过…

【分类】分类性能评价

评价指标 1、准确率、召回率、精确率、F-度量、ROC ​ 属于各类的样本的并不是均一分布&#xff0c;甚至其出现概率相差很多个数量级&#xff0c;这种分类问题称为不平衡类问题。在不平衡类问题中&#xff0c;准确率并没有多大意义&#xff0c;我们需要一些别的指标。 ​ 通…

PYTHON知识点学习-函数(下)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由 Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Mac安装brew、mysql、redis

mac安装brew mac安装brewmac安装mysql并配置开机启动mac安装redis并配置开机启动 mac安装brew 第一步&#xff1a;执行. /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"第二步&#xff1a;输入开机密码 第三…

element+vue table表格全部数据和已选数据联动

1.组件TableChoose <template><div class"tableChooseBox"><div class"tableRow"><div class"tableCard"><div class"tableHeadTip">全部{{ labelTitle }}</div><slot name"body" …

《奥本海默》热映,Sam Altman 会是下个他吗?

撰文&#xff1a;Nathan Gardels 来源&#xff1a;Noema 治理可能摧毁社会的技术。 图片来源&#xff1a;由无界AI生成 电影导演克里斯托弗 - 诺兰&#xff08;Christopher Nolan&#xff09;说&#xff0c;他曾与正在经历“奥本海默时刻”的人工智能科学家交谈过&#xff0c;他…

JavaScript 实现树形结构和一维数组互相转换

背景 树形结构和一维数组是开发中很容易碰到的情况&#xff0c;也是面试中很容易碰到的手撕题目 实现 一、一维数组转树形结构 FROM const source [{ id: 1, name: "张三", pid: 0 },{ id: 2, name: "李四", pid: 1 },{ id: 3, name: "王五&qu…

【【STM32--28--IO引脚的复用功能】】

STM32–28–IO引脚的复用功能 STM32的IO复用功能 何为复用? 我们先了解一下何为通用 IO端口的输入或输出是由GPIO外设控制&#xff0c;我们称之为通用 复用&#xff1a; IO端口的输入或者是输出是由其他非GPIO外设控制就像经常说的USART 由 DR寄存器进行输出 STM32的IO复用功…

Python学习教程:集合操作的详细教程

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 Python中有两种可以遍历的容器类型&#xff1a; 序列类型&#xff1a;包含字符串、列表、元祖 序列类型是线性表&#xff0c;就像数组一样&#xff0c;是在内存中开辟一块连续空间&#xff0c;连续存储的&#xff0c; 那么查找…

前端vue3+ts架构

1、vue creat 项目名称 选择自定义 选择需要的依赖 选择vue3 一路enter&#xff0c;选择eslistprettier 继续enter&#xff0c;等待安装 按步骤操作&#xff0c;项目启动成功 2、vscode安装5款插件 2、代码保存自动格式化&#xff0c;保证每个开发人员代码一致&#xff0c;根目…

震惊!靠「职业骗薪」,在上海买了别墅

昨天在知乎热榜上看到一条新闻&#xff0c;震惊之余&#xff0c;也有点可叹可悲的感觉。 根据经济观察报的报道&#xff1a;职业骗薪者&#xff0c;3 年在沪买别墅&#xff0c;同时供职 16 家公司却从不上班&#xff0c;落网时她还在面试。 新闻上说&#xff1a;管悦被警察抓获…

Bert和LSTM:情绪分类中的表现

一、说明 这篇文章的目的是评估和比较 2 种深度学习算法&#xff08;BERT 和 LSTM&#xff09;在情感分析中进行二元分类的性能。评估将侧重于两个关键指标&#xff1a;准确性&#xff08;衡量整体分类性能&#xff09;和训练时间&#xff08;评估每种算法的效率&#xff09;。…