JVM-详解G1垃圾收集器

剖析G1 垃圾回收器 G1最大的特点就是非常重视高吞吐量与软实时性的最佳平衡,它让用户来设定期望最大暂停时间(Stop the word),也就是在垃圾回收时停止所有用户线程的时间,G1垃圾收集器可以预测下次 GC 会导致应用程序暂停多长时间。 阅读详情

写这篇文章的原因是我看很多人提到G1的Full GC时都说是使用单线程回收,这个就很迷惑,虽然Full GC是在内存很紧张的时候才发生,但是既然都内存分块,为什么不能开多线程去并行回收,这样明显效率高很多,这点内存都不预留出来那设计G1回收的大佬是怎么考虑的?

G1垃圾回收在发生Full GC的时候由于全程单线程完全失去了内存分块意义,反而由于内存分块甚至比不分块还慢,这个问题已经在JDK10中改进了,感兴趣的可以看下官网的描述Parallel Full GC for G1,也就是说现在G1的Full GC其实是多线程处理的。可以灵活的设定Full GC时的工作线程数

由于上面问题的困扰,导致本人看了不少G1原理的文章,总感觉都讲的很复杂,很多很多概念性的东西,所以准备自己画一些图,对G1一些关键的机制做一个简单的说明。错误之处希望大家能够勘正,感谢🙏。

1.内存结构-为什么要将Java堆划分为多个Region?

基于分代收集理论实现的垃圾收集器,将Java堆分为两个区域,新生代和老年代。G1同样如此,G1将Java堆划分为多个Region区,每个Region有三个状态:未分配,新生代,老年代。

  • 因为新生代收集是基于复制算法实现的所以又分为Eden区,Survivor区
  • 老年代包括新生代中熬过多次回收后被复制到Old区的对象以及超过单个Region设定容量Humongous区

     

G1的创新之处在于每个区域可以灵活的根据当前状态去执行不同策略,同时做了很好的内存隔离,举个极端的例子,在不考虑跨区引用,且一块没有内存隔离的区域只能用一个线程去进行垃圾回收的情况下:

  • 对于G1之前的垃圾回收器假如使用1G的内存作新生代,那么其实在进行清理回收的时候只能是开1个线程去处理的,顶多可以开其他线程去处理别的请求,但是不能参与垃圾回收,这本质就是并发。
  • 而G1则是1G的内存作为新生代,同时又把这1G内存分为10个Region的话,那就可以开10个线程去并行处理,这样的回收速度远超单线程回收,当然了代价就是需要额外的内存去记录这些Region的信息。

     

上图是CMS(老年代)和G1(新生代+老年代)垃圾回收的主要过程,可以看出G1是并发标记+并行回收,而CMS则是并发标记+并发回收。并行回收看着简单其实实现难度还是很高的,要考虑很多因素,比如如何做到各个区域间的内存隔离,信息管理等,从提出理论到初步实现就花费了将近10年。

因为G1实现了模块化的内存管理模式,所以可以根据每个模块的状态以及内存利用率这些信息,提前计算出进行一次垃圾回收需要的时间等,从而去选择回收价值最高的先去回收。而CMS这种提前就把内存区域划分为两大块的做法就显得很笨重,同时也没有办法去控制回收的对象比例(主要还是在没有内存隔离的情况下实现这个需求太难了)。

问题结论:只有将Java堆划分为多个独立Region模块才能做到多线程并行回收

2.回收目标-什么是卡表CardTable,记忆集Remembered Set和写屏障Write Barrier?如何利用这些来定位需要回收的对象?

先提一下卡表的作用:卡表中存放着能够快速找到存在跨代引用的对象的索引,在进行非全局的GC时,可以凭借这种索引结构快速定位需要保留的对象。

G1是根据可达性算法来确定需要回收的目标,通过从GC Root Set包含的对象向下寻找引用链,来标记不能被回收的对象,在一个回收中,如果一个Region参与垃圾收集,那么在回收阶段,没有标记的对象将被全部清除。GC Roots由固定对象和临时对象构成。

  • 固定对象:
    • 虚拟机栈中引用的对象:线程中正在使用的对象
    • 方法区中类静态属性引用的对象:类中static声明的引用类型字段
    • 方法区中常量引用的对象:类中final声明的引用类型字段
    • 本地方法栈中引用的对象:native本地方法引用的对象
  • 临时对象:记忆集Remembered Set中保存的对象,可以理解为一个集合结构,里面放了一些同新生代有引用关系的老年代对象的地址,跟集合中对象有引用关系的对象就不会被回收,而卡表Card Table就是这个集合实现的一种方式

重点看下临时对象是怎么确定的,首先我们可以知道一个对象在哪个区域,这个区域是什么状态(新生代/老年代),当新生代中的对象引用了老年代对象时,就会把老年代的这个对象放入Remembered Set中,当作一个临时对象。

写屏障Write Barrier在其中的作用则类似Spring的AOP,当对象的赋值发生时,判断是不是老年代,如果是则通过统一的切面处理将引用对象的地址加入Remembered Set。(实际过程跟这个有出入,但我觉得如果不深究源码的话,这么理解是没有问题的)

下面画图来解释下CardTable的实现,可以理解为内存中建立的稀疏索引

G1的每个Region都是连续内存,Card Table第一行表示 Card Table的key为与当前Eden Reign存在引用关系的Old Region的内存起始位置,value是一个集合存储这临时对象所在的内存数组索引,,这就构成了一个稀疏索引。

比如1MB的内存,如果我们把其分为10个内存块,那么想确定这个Region中的一个临时对象最多只需要扫描100Kb即可,当对象的引用关系发生变化时,通过写屏障将key和value加入Card Table即可,代价也很明显就是为一个Region建立Card Table需要额外的空间,这个空间大小取决于索引段的大小,所以相同的Java堆内存,G1的内存使用率要低于CMS。

这种通过空间换时间的索引结构运用也很广泛,在Kafka,MySQL,Redis等中间件和数据库中都能见到。

3.回收过程-三种GC有哪些共同点和不同点?

先简单说明细不同的GC的目标类型,G1涉及 Young GC/Mixed GC/Full GC三种垃圾收集

  1. 部分收集(Partial GC):目标不是完整收集整个Java堆的垃圾收集

    • Minor GC/Young GC:新生代的垃圾收集
    • Major GC/Old GC:老年代的垃圾收集
    • Mixed GC:整个新生代及部分老年代的垃圾收集
  2. 整堆收集(Full GC):整个Java堆和方法区的垃圾收集。

Young GC

  1. 触发条件
    申请新的内存空间,在Eden区占据整个堆比例在允许范围内时,G1会计算现在Eden区回收大概要多久时间,如果回收时间远小于参数-XX:MaxGCPauseMills设定的值(默认200ms),那么增加新生代的Region,继续给新对象存放,不会马上做YoungGC。如果回收时间接近设定参数或者Eden空间不足则会发生进行一次Young GC

  2. 简图

     

    如何确定哪些对象需要回收,哪些需要保留前面已经提到过了就不多说了,保留的对象一部分复制到Survivor区,一部分达到晋升条件的移动到Old区,然后清除回收对象释放空间。
    Young GC全程暂停用户线程,进入STW,采用多线程并行的方式进行垃圾回收,每个线程负责部分Region。Young GC后如何还是无法获取足够Eden区空间,在进行一定次数的重试后会直接进行Full GC

Mied GC

  1. 触发条件
    在触发一次Young GC后,如果Old区占用的堆内存大小超过了InitiatingHeapOccupancyPercent参数设定的比例就会开始顺着Young GC已经调整标记的GC ROOTS进行并发标记->最终标记->清理的生命周期。
  2. 简图

Mixed GC并不会去回收全部的Old区对象,而是根据当前系统信息计算每个Region的回收价值,在设定的最大暂停内优先回收价值高的老年代Region。但是如果一次Mixed GC后空间还是不足,那么还会马上再次发起一次Mixed GC,超过最大设定的连续次数后就会进行Full GC

Full GC

在JDK9中,G1会直接采用原来的Serial Old来对整个堆垃圾收集,基于标记-清除-压缩算法来进行单线程回收,JDK10开始已经支持并行的Full GC,可以通过XX:ParallelGCThreads来设置并行的线程数

小结

上面是总结了部分作者对于G1垃圾收集器的看法,总的来说G1相比于之前的垃圾回收器最大的进步就是对于堆内存进行了更加精细的模块化管理,使其能够实现并行回收,能够更加自由的选定回收对象,设定回收时间,代价的话就是需要更多的空间来记录这些模块化的信息。如何选择还是要看实际的业务场景。
上面第三部分只是简单提了回收过程,涉及到过程中用到的SATB,TAMS,BitMap都没有详细去写

大白话详解G1垃圾回收器 通俗语言讲解G1垃圾回收器通过分代管理和Region划分优化堆内存管理,采用三色标记法进行垃圾回收,支持动态调整内存和设置停顿时间。 阅读详情

相关推荐

JVM G1垃圾回收器详细解析

Garbage First(简称G1)收集器摒弃了传统垃圾收集器的严格的内存划分,而是采用了基于Region的内存布局形式和局部回收的设计思路。G1垃圾收集器把Java堆划分为2048个大小相等的独立的Region,每个Region大小取值范围为1-32MB,且必须为2的N次幂参数,可以通过-XX:G1HeapRegionSize设定,-XX:G1HeapRegionSize默认为0,此时Region的大小采用Java堆大小/2048的计算公式来确定,取值为最接近的2的N次幂数值。

阿坨的博客 2372

JVM垃圾回收——G1垃圾收集器

Garbage First(简称G1)收集器是垃圾收集器技术发展史上里程碑式的成果,它摒弃了传统垃圾收集器的严格的内存划分,而是采用局部回收的设计思路和基于Region的内存布局形式。G1是一款主要面向服务端应用的垃圾收集器,在jdk6 update14时,就有了实验版本。而到了jdk7 update4之后移除了“Experimental”标识。它的目的是为了适应现在不断扩大的内存和不断增加的处理器数量,进一步降低暂停时间(pause time),同时兼顾良好的吞吐量。

weixin_39555954的博客 1万+

【JVM】第五篇 垃圾收集器G1和ZGC详解

ZGC收集器能仅从引用上就明确得知一个对象是否处于重分配集之中,如果用户线程此时并发访问了位于重分配集中的对象,这次访问将会被预置的内存屏障(读屏障)所截获,然后立即根据Region上的转发表记录将访问转发到新复制的对象上,并同时修正更新该引用的值,使其直接指向新对象,ZGC将这种行为称为指针的“自愈”Self-Healing)能力。统一存储器存储结构,表示内存只有一块,所有的CPU都去访问这一块内存,会存在内存竞争,有竞争就会有锁的问题,有锁就会影响执行的效率,并且CPU核心数越多,竞争就会越激烈。

入坑太深起不来 1359

详解G1垃圾收集器

G1(Garbage-First)作为继CMS之后新一代面向服务器的垃圾收集器,它已经不再严格按照之前老年代和新生代的划分来进行垃圾收集,即它是一个老年代和新生代共用的垃圾收集器。 G1更多是在多处理器(或多核)以及大内存的机器上发挥优势,在满足指定GC停顿时间要求的同时,还具备高吞吐量的能力。 这篇文章主要从G1的设计理念和垃圾回收过程来详细介绍。 一、设计思想 在《GC收集算法与GC收集器》这篇文章中介绍了JVM中经典的垃圾收集器,这些垃圾收集器的共性是在整个垃圾收集过程中,一定会发生Stop The

sermonlizhi的博客 1万+

Cadence仿真数字电路功耗

Cadence仿真数字电路功耗 数字电路的功耗采用平均电流乘电源电压获得,所以本文的关键是测量平均电流。 仿真前设置好仿真参数后,在仿真的ADE街边选择:outputs➡to be saved➡select on design 选择电源的负端电流(若选择正端,则电流为负): 选择完成后,在ADE界面讲所选节点的plot也勾选上,点击run。仿真完成后自动显示波形。在波形上选中该电流曲线,右击选择:send to➡calculator 注意上图中,商店前的波形不稳定,需要进行截取。在calculator

qq_41519780的博客 1万+

DSH-Work:一个让DeepSeek下载即用的Harness客户端

使用大模型工具时,环境配置往往比模型本身更让人头疼。DeepSeek Harness作为一类封装层,将模型调用、上下文管理、参数控制等复杂细节统一收拢,对外提供简洁操作入口。开源的DSH-Work正是这样一款Harness客户端,它通过自带运行时与保守默认配置,实现了下载即用、免配环境的目标,让使用者无需掌握Python、CUDA等专业知识即可快速连接DeepSeek云端或本地服务。对于非技术背景的用户,它降低了AI工具的使用门槛;对于开发者,它把时间从环境排错中解放出来,更专注于提示词调优与工作流设计。无

weixin_29048309的博客 346

详解 JVM Garbage First(G1) 垃圾收集器

版权声明:本文为博主原创文章,转载请联系作者并注明出处。 详解 JVM Garbage First(G1) 垃圾收集器 前言 Garbage First(G1)是垃圾收集领域的最新成果,同时也是HotSpot在JVM上力推的垃圾收集器,并赋予取代CMS的使命。如果使用Java 8/9,那么有很大可能希望对G1收集器进行评估。本文详细首先对JVM其他的垃圾收集器进行总结,并与G1进

coderlius的博客 9万+

ArcGIS实战:手把手教你用DEM和灾害点数据,5步搞定地质灾害风险区划图

本文详细介绍了使用ArcGIS进行地质灾害风险评估的完整流程,从DEM和灾害点数据出发,通过五步标准化操作生成专业风险区划图。重点讲解了信息量模型的应用,帮助读者掌握GIS技术在地质灾害易发性评价中的实践方法,提升风险评估效率与准确性。

weixin_30696427的博客 426

JVM调优-05-垃圾收集器G1详解

摘要 G1(Garbage-First)是一款面向服务器端的垃圾收集器,适用于多核处理器和大内存环境。它通过将堆划分为等大小的Region区域(默认2048个),动态调整年轻代和老年代占比(年轻代初始5%,最大60%),并引入Humongous区处理大对象。G1采用四阶段回收流程:初始标记、并发标记、最终标记和筛选回收,通过优先列表选择高效Region进行回收,确保在预设停顿时间(-XX:MaxGCPauseMillis)内完成垃圾收集。其特点包括并行/并发处理、分代收集、空间整合及可预测停顿。

weixin_41846452的博客 1354

核心组件大换血:Backbone与Neck魔改篇:YOLO26结合StarNet结构:2026星状网络在YOLO生态的即插即用实战

本文将介绍如何将StarNet作为Backbone替换YOLO26原生架构,以提升边缘设备上的目标检测性能。文章首先分析了YOLO26在特定场景下的精度瓶颈,指出其通用Backbone设计存在不足。随后深入解析StarNet的核心创新——星操作(Star Operation),这一低维计算却能获得高维特征表达的数学魔术,以及其极简的StarBlock模块设计。通过对比YOLO26原生架构的三大创新与痛点,作者提出两种替换策略:完整替换Backbone或局部替换+Neck联调。文中提供了StarNet核心代码

ZDQ58818的博客 290

4 屏 + 8 摄像头一开,谁在悄悄拖慢你的座舱域控?

如果你觉得座舱卡顿:❌ 别第一反应怪 SoC❌ 别盲目堆算力。

weixin_43199439的博客 150

JVM 垃圾收集器 G1 详解

这是一篇欠了自己很久的文章吧,一直想写一篇关于垃圾收集器 G1 的总结文章,却迟迟没有下笔哈哈,本篇将深入浅出带大家看看 G1 究竟给我们程序的垃圾收集带来了什么。

dying 搁浅 2007

Debezium报错处理系列之第112篇:Cannot replicate because the master purged required binary logs. Replicate the

Debezium报错处理系列之第112篇:Cannot replicate because the master purged required binary logs.

zhengzaifeidelushang的博客 727

JVM 垃圾收集器详解:CMS、G1 和 ZGC

垃圾回收(Garbage Collection, GC)是 Java 虚拟机(JVM)中一个至关重要的部分,尤其是在面对不同的业务场景时,选择合适的垃圾收集器(Garbage Collector, GC)对于优化 GC 性能至关重要。本文将详细介绍 JVM 中两大类垃圾收集器:分代收集器和分区收集器,并重点分析 CMS、G1 和 ZGC 这三种垃圾收集器的工作原理、优缺点及其适用场景

专注Java和MySQL领域知识分享 1933

【unity游戏开发入门到精通——UGUI】UI控件 —— Toggle开关切换控件

【unity游戏开发入门到精通——UGUI】UI控件 —— Toggle开关切换控件

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 1847

Halcon 形态学 开发案例 (开运算opening(先腐蚀再膨胀)、闭运算closing(先膨胀再腐蚀))

算子方法:功能:使用用户自定义的结构元素对区域进行开运算参数: Region(输入参数) :输入区域 StructElement(输入参数) :结构元素(区域) RegionOpening(输出参数) :开运算后的区域功能:使用圆形结构元素对区域进行开运算参数: Region(输入参数) :输入区域 RegionOpening(输出参数) :开运算后的区域 Radius(输入参数) :圆形结构元素的半径功能:使用矩形结构元素对区域进行开运算。

程序员,他们想的是什么?他们想的永远都是技术,他们崇尚的也永远都是技术。 1619

JVM-垃圾收集器G1&ZGC详解

图灵学院。若有违规,请留言 垃圾收集器G1&ZGC详解G1收集器(-XX:+UseG1GC) G1收集器(-XX:+UseG1GC) G1(Garbage-First)通过配置-XX:+UseG1GC开启使用G1垃圾收集器;它是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器。以及高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。   G1打破了之前版本对于JVM堆的分代划分。形成新的结构。它将java堆划分为多个大小相等的独立区域(Region),JVM目标是.

yz_ylfc的博客 1294

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

JVM的各种垃圾收集器详解(CMS、G1)

我们可以把垃圾回收器分为3类 串行、吞吐量优先、响应时间优先 其中,串行是单线程,吞吐量优先和响应时间优先是多线程 本文重点讨论的是分代收集器,ZGC会另外做一个文章专门讲解 1 串行(单线程) Serial收集器(复制算法)——新生代 Serial Old收集器(标记-整理算法)——老年代 单线程 对内存较小,适合个人电脑 采用复制算法-新生代,标记整理算法-老年代 -XX:+UseSerialGC=Serial+SerialOld——开启串行GC 回收过程 安全点: GC时,所有用户线程都会

minamisama的博客 697

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【jvm jdk】G1垃圾收集器详解

文章目录什么是G1垃圾收集器G1的堆内存划分G1的运行过程参考 什么是G1垃圾收集器 GC收集器的三个考量指标: 占用的内存(Capacity) 延迟(Latency) 吞吐量(Throughput) 随着硬件的成本越来越低,机器的内存也越来越大,GC收集器占用的内存基本上可以容忍。而吞吐量可以通过集群(增加机器)来解决。 随着JVM中内存的增大,STW的时间成为JVM急迫解决的问题,如果还是按照传统的分代模型,使用传统的垃圾收集器,那么STW的时间将会越来越长。 在传统的垃圾收集器中,STW的时间是无

m0_45406092的博客 819

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

JVM-G1垃圾收集器详解

JVM-G1垃圾收集器详解

weixin_45226668的博客 443

JVM性能调优-垃圾收集器G1详解

XX:G1HeapWastePercent(默认5%): gc过程中空出来的region是否充足阈值,在混合回收的时候,对Region回收都是基于复制算法进行的,都是把要回收的Region里的存活对象放入其他Region,然后这个Region中的垃圾对象全部清理掉,这样的话在回收过程就会不断空出来新的Region,一旦空闲出来的Region数量达到了堆内存的5%,此时就会立即停止混合回收,意味着本次混合回收就结束了。ZGC的停顿时间是在10ms以下,但是ZGC的执行时间还是远远大于这个时间的。

EverythingAtOnce的博客 2807

JVM Garbage First(G1) 垃圾收集器详解

G1(Garbage First)垃圾收集器是当今垃圾回收技术最前沿的成果之一。早在JDK7就已加入JVM的收集器大家庭中,成为HotSpot重点发展的垃圾回收技术。同优秀的CMS垃圾回收器一样,G1也是关注最小时延的垃圾回收器,也同样适合大尺寸堆内存的垃圾收集,官方也推荐使用G1来代替选择CMS。G1最大的特点是引入分区的思路,弱化了分代的概念,合理利用垃圾收集各个周期的资源,解决了其他收集器甚至CMS的众多缺陷。G1是一款非常优秀的垃圾收集器,不仅适合堆内存大的应用,同时也简化了调优的工作。

FJJJJJ 1165

JVM垃圾收集器详解 CMS、G1、Shenandoah、ZGC

上一篇我们讲解了一些垃圾回收的理论和一些基础的算法和思想,这一篇主要是jvm从古至今垃圾回收器的实现。 讲具体的实现之前,先说说几个和这些垃圾回收器息息相关的一些知识点,可以有一个更好的理解 ...

清风 1684
上一篇: 掌握高并发系统设计,面试弯道超车
下一篇: 字节跳动 3-3 大牛力荐!RabbitMQ 实战指南:消息队列面试必刷手册
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值