GC算法和常见垃圾回收器

news2025/1/21 11:59:25

一、GC算法

GC Algorithms(常见的垃圾回收算法),找到这个垃圾之后怎么进行清除的算法 。GC常用的算法有三
种如下:
1:Copying(拷贝)
2:Mark-Sweep(标记清除)
3:Mark-Compact(标记压缩)

第一个是Copying(拷贝)。非常简单,就是把内存一分为二,分开之后呢,把有用的拷贝到下面绿色
区域,拷贝完后上面全部清掉,回收完之后就变成下面的样子了,清楚简单。
在这里插入图片描述
第二个是叫Mark-Sweep,标记、清除。就是你把它标出来,然后清掉就这么简单。首先找到那些有用
的,没用的标出来然后给它清掉。
在这里插入图片描述
第三个Mark-Compact(标记压缩)。很简单,就是把所有的东西整理的过程,清理的过程同时压缩到头上去。回收之前,有用的全往前面走,哪怕这个地方是空的我也先给你压到前面去,剩下的大块空间就全部清出来了,这个叫标记压缩,整理完成之后就是下图这样的,看着特别爽,空间又是连续的还没有碎片。
在这里插入图片描述

二、GC算法问题

三种GC算法都有一定的问题,所以没法说哪个算法更加优越,看怎么使用。
1:copy算法逻辑简单,但是有一个显而易见的问题,就是空间浪费。
2:Mark-Sweep算法也有一个明显的问题,就是容易造成内存碎片。
3:Mark-Compact算法依然有它的问题,因为设计到对象的移动,移动的时候如果是多线程还要进行同步,效率较低,好处是不会产生内存碎片。

任何一个算法都有一定的问题,因此,java堆内存采用分代模型,垃圾回收器在不同的区域采用不同的回收算法。

在这里插入图片描述

一个对象产生之后首先进入伊甸区,伊甸区经过一次垃圾回收之后进入survivor区,survivor区在经过一次垃圾回收之后又进入另外一个survivor,与此同时伊甸区的某些对象也跟着进入另外一个survivor,什么时候年龄够了会进入到old区。
MinorGC/YGC: 年轻代空间耗尽时触发。
MajorGC/FullGC: 在老年代无法继续分配空间时触发,新生代老年代同时进行回收。

三、常见垃圾回收器

在这里插入图片描述
G1和ZGC在物理上已经不分代了。

3.1 Serial

在这里插入图片描述
很简单使用单线程进行垃圾回收,GC线程工作的时候会发生STW,所有的业务线程都会停止。

3.2 Serial Old

这个用在老年代,他用的是mark-sweep的算法,用的也是单线程,和Serial一样,同样会发生STW。

3.3 Parallel Scavenge

在这里插入图片描述
理解了Serial,就很容易理解Parallel Scavenge。Parallel Scavenge采用多线程来进行垃圾回收。本质的原因是,随着服务器内存不断增大,单进程的GC有点力不从心了。

3.4 Parallel Old

  • a compacting collector that uses multiple GC threads

用在老年代,和Parallel Scavenge的组合简称PS+PO,这个也是jdk1.8默认使用的垃圾回收器。

3.5 ParNew

和Parallel Scavenge基本没什么区别,就是为了和CMS配合使用推出的。

3.6 CMS(concurrent mark sweep)

CMS是一个里程碑式的垃圾回收器,原来的垃圾回收器在工作的时候,业务线程必须STW。CMS全称是并发标记清除垃圾回收器,允许GC线程和业务线程同时进行。CMS出现的本质原因是,随着服务器内存不断增大,GC线程并不是越多效率就越高,当内存很大的时候,多线程的GC,STW的时间也会很长。但是CMS毛病非常多。以至于目前任何jdk版本默认都不是CMS
在这里插入图片描述

  1. 第一个阶段叫做CMS initial mark(初始标记阶段)。很简单, 就是我直接找到最根上的对象,其他的对象我不标记,直接标记最根上的。会发生STW,但时间会很短。
  2. 第二个是CMS concurrent mark(并发标记),据统计百分之八十的GC的时间是浪费在这里,因此它把这块最浪费时间的和我们的应用程序同时运行,这是并发标记。就是你一边产生垃圾,我这一边跟着标记但是这个过程是很难完成的。
  3. 所以最后又有一个CMS remark(重新标记)。这又是一个STW。在并发标记过程中产生的那些垃圾在重新给它标记一下,这个时候需要业务线程停一下,时间不长。
  4. 最后是一个concurrent sweep(并发清理)的过程。并发清理也有它的问题,并发清理过程也会产生新的垃圾啊,这个时候的垃圾叫做浮动垃圾,浮动垃圾就得等着下一次CMS再一次运行的过程把它给清理掉。

在第二阶段并发标记是很容易发生错标的,这里使用了著名的三色标记法。

3.6.1 三色标记法

在这里插入图片描述
如果一个对象自己已经完成标记,并且fields都完成了标记,那么这个对象就是黑色的。
如果一个对象自己标记完成,fields还没有标记,那么这个对象就是灰色的。
如果一个对象还没有被GC线程遍历到,那么这个对象是白色的。

因为业务线程是在运行中的,对象的引用有可能会发生变化,比如:
在这里插入图片描述
下一次操作系统调度GC线程进来的时候,B–>D消失,A–>D增加
在这里插入图片描述
这时候就会有问题,本来A已经标记为黑色了,不会去扫子节点,B灰色的,应该去扫子节点,但是指向子节点D的引用消失了,这时D就标记不到,成为了垃圾,这是错误的。所以当一个黑色对象,增加一个新的引用的时候,GC要把这个对象重新变为灰色,这是CMS的解决方案,这种算法叫做incremental update(增量更新)
在这里插入图片描述
CMS是一款低延迟的垃圾回收器,牺牲了一定的吞吐量。

3.7 G1

G1是一款服务端应用使用的垃圾回收器,目标是用在多核、大内存的机器上,它在大多数情况下,可以实现指定的GC暂停时间,同时还能保持较高的吞吐量。

3.7.1 分区

由于堆内存十分巨大,G1采用了分而治之的思想,也就是分区,把内存分为一小块一小块的region,从1M2M最大到32M。每一份region在逻辑上依然属于某一个分代,这个分代分为四种,第一种Old区都是放老对象的、Survivor区放存活对象的、Eden区放新生对象的、Humongous区大对象区域,对象特别大有可能会跨两个region。所以G1的内存模型已经完完全全的和以前的分代模型不一样了。region的角色并不是固定不变的。
在这里插入图片描述

3.7.2 GC

1、YGC
JVM启动时,G1先准备好Eden区,程序在运行过程中不断创建对象到Eden区,当Eden空间耗尽时,G1会启动一次年轻代回收过程。YGC时,会发生STW。需要注意的是,每次GC时,所有的新生代都会被扫描。
特别需要注意的是,根对象有可能在Old区,然后Old区可能也指向Eden区的对象,那么是否扫描新生代还要扫描整个老年代,这显然是不可取的。G1使用RSet来记录并跟踪Region间的对象引用关系,每个Region初始化时,也会初始化一个RSet,RSet记录其它Region指向本Region对象的记录。
在这里插入图片描述
上图中有三个Region,每个Region被分成了多个Card,在不同Region中的Card会相互引用,Region1中的Card中的对象引用了Region2中的Card中的对象,Region3中的Card中的对象引用了Region2中的Card中的对象,所以Region2的RSet记录了这些引用。
如果一个Old区Card中有对象指向新生代,就将它设为Dirty,只需要扫描这些Dirty的就可以了。
2、MixedGC(混合GC)
当堆内存使用达到一定值时,默认45%(-XX:InitiatingHeapOccupancyPercent),就启动了MixedGC,MixedGC即会回收新生代,也会回收部分老年代。MixedGC时和CMS一样也经历了4个阶段:

  • 初始标记 STW
  • 并发标记(三色标记法)
  • 重新标记 STW
  • 筛选回收 STW (并行)

初始标记时,会触发一次YGC。
并发标记时,会计算每个Region的对象活性,也就是存活对象的比例。
重新标记时,使用了效率更高的SATB算法,不同于CMS的增量更新。
筛选回收时,不会回收整个Old区,而是根据Region的对象活性,从中挑选几个回收价值高的Region进行回收,尽可能达到指定的GC暂停时间(-XX:MaxGCPauseMillis)。也就是说,如果GC指定暂停时间设置的比较少,那么从Old回收的Region就会比较少。

3、FGC
G1的设计初衷就是为了避免FullGC的出现,如果出现了FullGC,可以从下面两点调整:

  • 扩内存
  • 降低MixedGC触发的阈值,让MixedGC提早发生(默认是45%)

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

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

相关文章

Linux常用命令----cp 命令

文章目录 1. 基本用法2. 保留文件属性3. 递归复制4. 仅复制更新的文件5. 交互式复制6. 创建符号链接而非复制7. 复制并备份目标文件8. 指定备份后缀9. 详细输出总结 Linux操作系统中,cp 命令是一个非常基础且强大的工具,用于复制文件或目录。本文将详细介…

C语言进阶指南(16)(自定义数据类型——结构体)

欢迎来到博主的专栏——C语言进阶指南 博主id:reverie.ly 文章目录 结构体类型结构体类型的声明结构体变量的声明 结构体变量的初始化结构体变量结构体变量的赋值结构体变量的成员结构体变量的使用结构体变量的内存存储 前面使用的变量都是简单类型的变量&#xff0…

赴日开发做什么?日本签证很难拿?

日本的IT行业历史比较悠久,业务以上层前端业务为主,如设计和构建软件。日本IT公司组织庞大,行业内部有着严格的分工和部署,工作会被细分化。分配给个人的工作量不会太大,难度也不会很高。 在日本IT公司就业&#xff0…

XUbuntu22.04之隐藏顶部任务栏(一百九十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

Java常见CodeReview及编码规范

鉴于自己的开发经验,以及常见容易产生bug及性能问题的点做个记录. 1.数据库 如果开发人员的经验不足,Java通过ORM(Mybatis)对数据库的操作的性能问题比较隐蔽.因为不压测或者异常case没发生的时候一般发现不了问题.特别是异常case发生的时候. 除配置表以外的sql都要经过expl…

悠络客荣获“供应链服务之星”“供应链服务之星最佳人气奖”两项殊荣

11月28日,由AC汽车主办的第八届汽车后市场连锁百强&TOP品牌颁奖典礼在上海盛大举行。超300家企业欢聚一堂,共同见证一年一度的荣耀时刻! 经过线上征集、评选组提名、网络投票和专家评审等多轮评选,悠络客在全国众多参赛品牌中…

jenkins使用nexus插件

nexus介绍 Nexus 是一个强大的仓库管理工具,用于管理和分发 Maven、npm、Docker 等软件包。它提供了一个集中的存储库,用于存储和管理软件包,并提供了版本控制、访问控制、构建和部署等功能。 Nexus 可以帮助开发团队提高软件包管理的效率和…

二叉树(判断是否为对称二叉树)

题目(力扣): 观察题目,只需判断该二叉树是否对称。 判断二叉树是否对称,就可以换位去判断该二叉树的左子树和右子树是否对称。 这时就可以写一个辅助函数来方便判断。 该函数是判断两颗树是否镜像对称,这…

分布式文件系统之HDFS

前言 一、HDFS简介 1.1 HDFS产出背景及定义 1)HDFS产生背景 先给大家介绍一下什么叫HDFS,我们生活在信息爆炸的时代,随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中&a…

C++中用于动态内存的new和delete操作符

文章目录 1、动态分配内存的应用2、动态分配内存与分配给普通变量的内存有什么不同?3、C 中如何分配/释放内存4、new 操作符4.1 使用new的语法4.2 初始化内存4.3 分配内存块4.4 普通数组声明 Vs 使用new4.5 如果运行时没有足够内存可用怎么办? 5、delete 操作符 C/…

【知识】简单理解为何GCN层数越多越能覆盖多跳邻居聚合信息范围更广

转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 大多数博客在介绍GCN层数时候,都会提到如下几点(经总结): 在第一层,节点聚合来自其直接邻居的信息。在第二层,由于每个节点现在包含了其直接邻居的信息&a…

flink源码分析之功能组件(四)-slotpool组件I

简介 本系列是flink源码分析的第二个系列,上一个《flink源码分析之集群与资源》分析集群与资源,本系列分析功能组件,kubeclient,rpc,心跳,高可用,slotpool,rest,metrics&…

树与二叉树堆:链式二叉树的实现

目录 链式二叉树的实现: 前提须知: 前序: 中序: 后序: 链式二叉树的构建: 定义结构体: 初始化: 构建左右子树的指针指向: 前序遍历的实现: 中序…

J-Flash工具的使用---擦除、烧录及校验

文章目录 前言一、打开J-Flash工具二、使用步骤1.创建工程,选择MCU,配置端口2.打开要烧录的文件3.连接J-Link4.擦除Flash5. 烧录固件 总结 前言 不使用IDE(如keil、Iar)如何来烧录固件。当我们的程序需要保密,不需要被…

汽车悬架底盘部件自动化生产线3d检测蓝光三维测量自动化设备-CASAIM-IS(2ND)

随着汽车工业的不断发展,对于汽车零部件的制造质量和精度要求也在不断提高。汽车悬架底盘部件作为汽车的重要组成部分,其制造质量和精度直接影响到整车的性能和安全性。因此,采用CASAIM-IS(2ND)蓝光三维测量自动化设备…

滴滴也崩了!

昨日,据国内多家媒体报道,从11月27日晚上开始,滴滴因系统故障导致App服务异常,不显示定位且无法打车。 这次瘫痪事件持续了12个小时,根据滴滴公布的2023年第三季度财报,滴滴出行日均单量达到3130万单&#…

【老文新发】Otsu大津法详解及python实现

原文:A Threshold Selection Method from Gray-Level Histograms A Fast Algorithm for Multilevel Thresholding 前言 大津法包含两个重要的概念:类间方差(between-class variance)和类内方差(within-class varianc…

Linux地址空间随机化

ASLR(Address Space Layout Randomization)在2005年被引入到Linux的内核 kernel 2.6.12 中,早在2004年就以补丁的形式引入。内存地址的随机化,意味着同一应用多次执行所使用内存空间完全不同,也意味着简单的缓冲区溢出攻击无法达到目的。 1.…

LeetCode(39)赎金信【哈希表】【简单】

目录 1.题目2.答案3.提交结果截图 链接: 赎金信 1.题目 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字…