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

详解垃圾回收算法,优缺点是什么?|金三银四系列

本文详细介绍了在 JVM 中如何判断哪些对象是需要回收的,以及不同的垃圾回收算法以及优缺点。

点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达

上篇文章详细介绍了 JVM 的结构以及其内存结构,需要阅读请移步。本文主要讲解 JVM 体系中的垃圾收集子系统用到的内存回收算法。

八股文总是忘?一张图牢记JVM内存结构|金三银四系列

2023-02-13

5926b63b143ec579287e6aead989b947.jpeg

哪些对象需要回收

在进行垃圾回收之前,第一件事就是确定哪些对象还存活着,哪些对象已死需要被回收。

1.引用计数算法

很多判断对象是否存活的算法是这样的:

  • 给对象中添加一个引用计数器,每当有个地方引用它时,计数器值就加1;

  • 当引用失效时,计数器值就减1,任何时刻计数器为0的对象就是不可能再被使用的,该对象将被回收。

客观的说,引用计数法实现简单,效率高。但是没有主流JVM选择引用计数法管理内存,因为他无法解决循环引用的问题。如下图e842668b80bb60dface491a0fcdabaab.png

当三个对象都不在使用时,因为相互的引用关系,并不会置为0,所以难以被回收。并且,引用计数器要求在每次因引用产生和消除的时候,伴随一个加法操作和减法操作,对系统性能会有一定的影响。

2.可达性分析算法

主流JVM都是称通过可达性分析来判定对象是否存活的。这个算法的基本思路就是通过一系列的称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链( Reference Chain),当一个对象到GC Roots 没有任何引用链相连,用图论的话来说,就是从GC Roots 到这个对象不可达) 时,则证明此对象是不可用的。

如图所示,深灰色的对象虽然互相有关联,但是它们到 GC Roots 是不可达的,所以它们将会被判定为是可回收的对象。

4270f5a84c017e8428e7fa377680a584.png

GC Root 对象

Java中,有一组GC Roots对象,它们是被垃圾回收器直接管理的对象。GC Roots对象是垃圾回收的起始点,垃圾回收器会从这些对象开始遍历所有的对象,并标记出所有存活的对象,未被标记的对象即为可回收对象。

在Java中,可以作为GC Root对象的包括以下几类:

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。虚拟机栈中保存着每个线程执行方法时的现场信息,包括局部变量、操作数栈、方法出口等。栈帧中的本地变量表中存放着方法中定义的局部变量和参数,如果局部变量或参数中引用了某个对象,则该对象被认为是一个GC Root对象。

  2. 方法区中类静态属性引用的对象。类似于栈帧中的本地变量表,类中定义的静态属性也会保存引用对象。因为静态属性是属于类的,所以这些引用对象也被认为是GC Root对象。

  3. 方法区中常量引用的对象。常量池中保存着编译器生成的各种字面量和符号引用,例如字符串常量、类和接口的全限定名、字段和方法的名称和描述符等。如果常量池中引用了某个对象,则该对象被认为是GC Root对象。

  4. 本地方法栈中JNI(即Java Native Interface)引用的对象。JNI是Java提供的一种机制,用于调用本地的C/C++代码。如果JNI中引用了某个对象,则该对象被认为是GC Root对象。

需要注意的是,不是所有的对象都可以作为GC Root对象。例如,普通的对象实例和数组元素就不可以作为GC Root对象。只有与Java虚拟机内存管理有关的对象才可以作为GC Root对象,因为它们直接或间接地引用了所有其他对象。

垃圾回收算法

1.标记-清除算法

最基础的收集算法是标记-清除算法(Mark-Sweep),如同它的名字一样,算法分为“标记”和“清除”两个阶段:

  1. 首先标记出所有需要回收的对象(可达性分析)。

  2. 在标记完成后统一回收所有被标记的对象。

之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其不足进行改进而得到的。

ba5f192822c567b9bf2f0b75fa10abe6.png

优点

  • 实现简单,算法简单、容易实现,与保守式GC 算法兼容,有效处理不连续的内存空间

  • 不需要移动对象,因此不会浪费时间和空间。

不足

  • 效率问题:标记和清除两个过程的效率都不高,且需要进行两次扫描,第一次标记垃圾对象,第二次清除垃圾对象。

  • 空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作,从而导致频繁的内存分配和回收。

2.标记-压缩算法(标记-整理)

标记压缩算法(Mark-Compact)是一种垃圾回收算法,主要用于老年代的垃圾回收。它的基本思想是在标记出所有存活对象之后,将所有存活的对象压缩到内存的一端,将所有空闲的内存空间释放出来,从而减少内存的碎片化。

标记压缩算法与标记-清除算法的区别在于,标记-清除算法只是标记出存活和垃圾对象,并将垃圾对象空间释放出来,因此容易造成内存的碎片化。而标记压缩算法则是将存活对象压缩到一端,并将空闲的内存空间释放出来,解决了内存碎片的问题。

7c2acabbd043df28537b9daae7e77838.png

标记压缩过程

标记压缩算法的具体实现过程如下:

  • 标记阶段:从一组 GC Roots 开始,标记出所有存活的对象,并将这些存活对象的标记信息保存在对象头中。

  • 压缩阶段:将所有存活的对象移动到内存的一端,释放出所有空闲的内存空间。在移动对象时,需要更新所有引用对象的指针,确保它们指向对象移动后的位置。

  • 更新指针:由于移动对象的过程中,可能会修改引用对象的指针,因此需要扫描整个堆内存,将所有指向移动过的对象的指针进行更新。(这不算一个阶段)

由于需要更新所有引用对象的指针,因此在多线程情况下,需要使用屏障技术来确保线程安全性。

优点

  • 可以有效地处理不连续的内存空间。

  • 不会产生内存碎片,因为所有存活的对象都被移动到一端。

缺点

  • 压缩阶段需要移动存活的对象,占用了系统的消耗,并且如果标记对象过多的话,损耗可能会很大,会浪费时间和空间。在标记对象相对较少的时候,效率较高。

  • 需要进行两次扫描,第一次标记存活对象,第二次移动存活对象。

为什么没有清除阶段

标记-整理算法确实只有标记和整理两个阶段,没有显式的清除阶段。在整理阶段,垃圾回收器会将所有存活的对象向一端移动,将空间释放到另一端,这样空间的连续段就被重建了。因此,整理阶段的同时也具有清除的功能,所有未被移动的对象都是垃圾,可以直接被视为已经清除了。不过,在实现时,标记-整理算法的整理阶段可能需要把清除的操作分散在整个过程中进行,因此整理阶段通常会和清除阶段结合在一起,实现起来会更加高效。但是从逻辑上来说,标记-整理算法只需要标记和整理两个阶段,没有显式的清除阶段。

复制算法

为了解决效率问题,一种称为“复制”(Copying)  的收集算法出现了,它将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存话着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效,算是用空间来换时间的思维。

f51ff8b97946e22088ddd24cc8fb8749.png

优点

  • 可以有效地处理大部分对象都是临时对象的情况,例如新生代中的对象。

  • 不会产生内存碎片,因为所有存活的对象都被复制到一个新的内存空间中。

缺点

  • 需要一半的内存空间用于复制存活的对象,会造成空间浪费。

  • 当有大量存活的对象时,复制效率会降低。

4.分代收集算法

目前主流JVM垃圾收集都采用“分代收集”(Generational Collection) 算法,这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保(如果有空间,通过分配担保机制进入老年代),就必须使用“标记一清理”或者“标记一整理”算法来进行回收。

d6b13e476aeb037d03e5dc38fca39632.png

对于新生代和老年代来说,通常新生代回收的频率很高,但是每次回收的时间都很短,而老年代回收的频率比较低,但是被消耗很多的时间。为了支持高频率的新生代回收,虚拟机可能使用一种叫做卡表(Card table)的数据结构,卡表为一个比特位集合,每一个比特位可以用来表示老年代的某一区域中的所有对象是否持有新生代对象的引用。

这样以来,新生代GC时,可以不用花大量时间扫描所有老年代对象,来确定每一个对象的引用关系,而可以先扫描卡表,只有当卡表的标记为1时,才需要扫描给定区域的老年代对象,而卡表为0的所在区域的老年代对象,一定不含有新生代对象的引用。

卡表中每一位表示老年代4KB的空间,卡表记录为0的老年代区域没有任何对象指向新生代,只有卡表为1的区域才有对象包含新生代对象的引用,因此在新生代GC时,只需要扫面卡表为1所在的老年代空间,使用这种方式,可以大大加快新生代的回收速度。

优点

  • 根据对象的生命周期,将堆分为多个区域,使不同区域采用不同的回收算法,可以提高回收效率。

  • 可以避免全局垃圾回收的情况,从而减少了暂停时间。

缺点

需要维护多个堆区域,增加了复杂性。可能会出现对象晋升的情况,导致老年代的内存压力增大。

5.分区算法

分代算法将按照对象的生命周期长短划分成两个部分,分区算法将整个堆空间划分成不同连续的区域。每个小区间都独立使用,采用不同的垃圾回收算法,独立回收。例如,可以将新生代分成多个区域,每个区域采用不同的复制算法,而老年代则采用标记-整理或标记-清除算法。这种算法的好处是可以控制一次回收多少个小区间。

一般来说,在相同的条件下,堆空间越大,一次GC时所需要的时间就越长,从而产生的停顿也越长。为了更好地控制GC产生的停顿时间,将一块大的内存区域分割为多个小块,根据目标的停顿时间,每次合理的回收若干个小区间,而不是整个堆空间,从而减少一次GC所产生的停顿。这算是一种分治思路。

最后,欢迎大家提问和交流。

如果对你有帮助,欢迎点赞、评论或分享,感谢阅读!

无需注册直接体验ChatGPT!附注册ChatGPT详细教程

2023-02-14

bb054b3cd2787f7fac19b137d8bb9d92.jpeg

一文掌握,单机Redis、哨兵和Redis Cluster的搭建,建议收藏

2023-02-11

43b550370b477d56fd2da031ced758d8.jpeg

Dubbo重点,SPI的自适应扩展原理|原创

2023-01-11

9cf7e6e74a7aa97346ef9c377fd3e601.jpeg

相关文章:

详解垃圾回收算法,优缺点是什么?|金三银四系列

本文详细介绍了在 JVM 中如何判断哪些对象是需要回收的,以及不同的垃圾回收算法以及优缺点。点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达上篇文章详细介绍了 JVM 的结构以及其内存结构,需要阅读请移步。本文主要…...

Android 虚拟 A/B 详解(七) SnapshotManager 之标识文件

本文为洛奇看世界(guyongqiangx)原创,转载请注明出处。 原文链接:https://blog.csdn.net/guyongqiangx/article/details/129098176 Android 虚拟 A/B 分区《Android 虚拟 A/B 分区》系列,更新中,文章列表: Android 虚拟 A/B 详解(一) 参考资料推荐Android 虚拟 A/B 详解(二…...

LA@生成子空间@范数@衡量矩阵大小@正交化

文章目录线性组合与线性方程组生成子空间范数LpL^pLp范数向量点积用范数表示ref衡量矩阵大小特殊类型矩阵和向量对角阵向量长度性质单位向量向量单位化(正规化)正交向量正交正交向量组标准正交基正交化(schmidt)正交矩阵矩阵是正交矩阵的充要条件对称矩阵正交相似概念区分&…...

MT2012_竹鼠的白色季节

竹鼠的白色季节 #include<bits/stdc.h> #include<algorithm> using namespace std;/*思路&#xff1a;从小到大排序&#xff0c;然后依次往后遍历即可*/ int main( ) {int n,d;cin>>n>>d; int tmp;vector<int>nums;for(int i0;i<n;i){cin&…...

MySQL是什么?它有什么优势?

随着时间的推移&#xff0c;开源数据库在中低端应用中逐渐流行起来&#xff0c;占据了很大的市场份额。开源数据库具有免费使用、配置简单、稳定性好、性能优良等特点&#xff0c;而 MySQL 数据库正是开源数据库中的杰出代表。 开源全称为“开放源代码”。很多人认为开源软件最…...

基础篇—CSS padding(填充\内边距)解析

CSS padding(填充) CSS padding(填充)是一个简写属性,定义元素边框与元素内容之间的空间,即上下左右的内边距。 属性说明padding使用简写属性设置在一个声明中的所有填充属性padding-bottom设置元素的底部填充padding-left设置元素的左部填充padding-right设置元素的右部…...

二进制枚举

一、左移&#xff1a;用来将一个数的各二进制位全部左移n位&#xff0c;低位以0补充&#xff0c;高位越界后舍弃。n左移1位&#xff0c;n<<1&#xff0c;相当于2*n1左移n位&#xff0c;1<<n&#xff0c;相当于2^n二、右移&#xff1a;将一个数的各二进制位右移N位&…...

2|数据挖掘|聚类分析|k-means/k-均值算法

k-means算法k-means算法&#xff0c;也被称为k-平均或k-均值&#xff0c;是一种得到最广泛应用的聚类算法。算法首先随机选择k个对象&#xff0c;每个对象初始地代表了一个簇的平均值或中心。对剩余的每个对象根据其与各个簇中心的距离&#xff0c;将它赋给最近的簇。然后重新计…...

使用和制作动、静态库

文章目录什么是库&#xff1f;静态库打包方式使用方式生成并执行可执行程序粗暴方式优化方式动态库不一样的.o文件打包方式使用方式生成可执行程序运行可执行程序无法运行时的解决方案动静态库与动静态链接什么是库&#xff1f; 从一开始的helloworld&#xff0c;到现在熟练使…...

【Java基础】023 -- 集合进阶(List、Set、泛型、树)

目录 一、集合的体系结构 1、单列集合&#xff08;Collection&#xff09; 二、Collection集合 1、Collection常见方法 ①、代码实现&#xff1a; ②、contains方法重写equals方法示例&#xff1a;&#xff08;idea可自动重写&#xff09; 2、Collection的遍历方式&#xff08;…...

面试题整理01-集合详解

文章目录前言一、集合的整体结构单列集合接口&#xff1a;双列集合接口&#xff1a;二、单列集合详解1.List接口1.1 ArrayList集合特点&#xff1a;扩容&#xff1a;添加元素遍历1.2 LinkedList集合特点&#xff1a;添加元素&#xff1a;2.Set接口2.1 HashSet集合特点&#xff…...

数据驱动的两阶段分布鲁棒(1-范数和∞-范数约束)的电热综合能源系统研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

ArcGIS网络分析之发布网络分析服务(二)

在上一篇中讲述了如何构建网络分析数据集,本篇将讲解如何发布网络分析服务。本文将使用上一篇中建立的网络数据集,下载地址在上一篇博文的最后已给出。 之前我们已经实现了基于ArcMap中的网络分析,但是仅仅支持本地是万万不够的,这里我们的目的就是将我们建好的网络分析图…...

js实现元素样式切换的基本功能

需求&#xff1a;用户第一次点击某些元素&#xff0c;改变元素的某些样式&#xff0c;比如背景颜色&#xff0c;字体颜色。用户第二次点击某些元素&#xff0c;恢复之前的样式。.....思路&#xff1a;准备一定量的div盒子&#xff0c;并取相同的类名<div class"box&quo…...

java 策略模式 + 工厂模式 实例

一 前言 经常听说各种设计模式&#xff0c;知道理论&#xff0c;也知道应该使用&#xff0c;但具体怎么用&#xff0c;什么时候用&#xff0c;使用的优点一直比较模糊&#xff0c;今天写一个项目中经常用到的模式&#xff0c;来具体理解。项目中经常用到工厂模式或者策略模式&…...

本地生成动漫风格 AI 绘画 图像|Stable Diffusion WebUI 的安装和部署教程

Stable Diffusion WebUI 的安装和部署教程1. 简介2. Windows安装环境3. 运行4. 模型下载链接5. 其他资源1. 简介 先放一张WebUI的图片生成效果图&#xff0c;以给大家学习的动力 &#xff1a;&#xff09; 怎么样&#xff0c;有没有小小的心动&#xff1f;这里再补充一下&…...

华为OD机试 - 异常的打卡记录 | 备考思路,刷题要点,答疑 【新解法】

最近更新的博客 【新解法】华为OD机试 - 关联子串 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 停车场最大距离 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试 - 任务调度 | 备考思路,刷题要点,答疑,od Base 提供【新解法】华为OD机试…...

「机器学习笔记」之深度学习基础概念(基于Pytorch)

本文以 Pytorch 为线索&#xff0c;介绍人工智能和深度学习相关的一些术语、概念。 关于发展历史您也可以阅读深度学习神经网络之父 Jrgen Schmidhuber 所写的《Annotated History of Modern AI and Deep Learning&#xff08;现代人工智能和深度学习的注释版历史&#xff09;…...

概率和似然

在日常生活中&#xff0c;我们经常使用这些术语。但是在统计学和机器学习上下文中使用时&#xff0c;有一个本质的区别。本文将用理论和例子来解释概率和似然之间的关键区别。 概率与似然 假设在一场棒球比赛中&#xff0c;两队的队长都被召集到场上掷硬币。获胜的队长将根据掷…...

前期软件项目评估偏差,如何有效处理?

1、重新评估制定延期计划 需要对项目进行重新评估&#xff0c;将新的评估方案提交项目干系人会议&#xff0c;开会协商一致后按照新的讨论结果制定计划&#xff0c;并实施执行。 软件项目评估偏差 怎么办&#xff1a;重新评估制定延期计划2、申请加资源 如果项目客户要求严格&a…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...