JVM学习日志(十三) G1垃圾回收流程 及 垃圾回收器总结

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: G1垃圾回收流程 及 垃圾回收器 总结 简述

G1垃圾回收流程

image-20230506113751177.png

G1的垃圾回收流程主要是从新生代回收开始,新生代回收与并发标记再打混合回收,接下来我们就先说第一个新生代回收

G1 Young Collection

当我们的程序启动刚开始的时候,会默认分配新生代5%的空间,这里我们假设分配了8个Region给Eden, 1个Region给Survior(只是为了画图方便,实际上可能Eden对应了有好几十甚至上百个Region),那么对应的初始内存分配如下:

image-20230506114004719.png

那么当我们的Eden区域装满,还是会触发新生代的GC,那么新生代的GC还是会通过复制算法来进行垃圾回收,同时系统进入到"Stop The World"状态,然后把Eden区中的对应的Region里存货的对象拷贝到S1对应的Region中,接着回收掉Eden对应的Region中的垃圾对象

注意并不是Eden区一满就会立马触发新生代GC,G1会计算现在Eden区回收大概需要多久的时间,如果远远小于默认的200ms,那么就会继续增加新生代的Region,继续存放新的对象,直到下一次Eden区满再计算回收时间,如果时间接近200ms或者设置的值,则触发MionrGC

需要注意的是:

再触发空间担保的情况下,G1是不会将大对象直接存储到堆空间中,而是有专门的大对象存储的区域Humongous

Humongous区域的大对象什么时候会被回收呢,其实很简单,再新生代和老年代的对象回收的时候,就会顺带着堆大对象一并回收,所以这就是G1内存模型下对大对象的分配和回收的策略

注意

再G1进行新生代垃圾回收的同时还会做一件事情就是"初始标记":仅仅只是标记一下GCRoots能直接关联到的对象,对下一阶段并发标记做准备(跟之前的CMS垃圾回收过程类似)

当G1新生代垃圾回收结束之后,紧接着开始进入并发标记阶段,从GCRoot开始对堆中的对象进行可达性分析,递归扫描整个堆里的对象图,找出来要回收的对象,这阶段耗时比较长,但是可与用户程序并发执行

而且JVM会对并发标记阶段对对象做出的一些修改记录起来,比如那个对象被新建了,那个对象失去引用了

G1 Mixed Conllection

G1有一个参数:"-XX:InitiatingHeapOccupancyPercent"默认值是45%

也就是说:当老年代的大小占据了堆内存的45%的Region时,此时就会触发一个新生代和老年代的混合回收阶段,对ES0H进行全面回收

该阶段一旦触发会导致系统进入STW,同时进行最后一个标记

最终标记阶段:

会根据并发标记阶段记录的对象修改,最终标记那些对象是存活,那些对象是垃圾

此时老年代也是根据标记-复制算法来进行回收,会将标记存活的对象拷贝到新的Region中作为老年代区域

注意我们上面说过得一个参数: -XX:MaxGCPauseMillis=time指定收集的停顿时间,默认是200ms

由于混合回收是一个比较耗时的操作,那么根据G1的特点可以指定收集停顿时间,为了保证停顿时间这个目标,JVM会从新生代,老年代,以及大对象H区挑选一部分Region进行拷贝回收,如果回收不完,后续在进行回收,一部分一部分回收直到回收完毕,但是一次回收的停顿时长保证再200MS

这里有一个参数"-XX: G1MixedGCCountTarget",可以设置在一次回合回收的过程中,最后一个阶段执行几次混合回收,默认值是8次,这样设置的目的也是能让每次会后停顿的时长记得到保证同时又能间隙的让系统接着运行

同时还有一个参数"-XX:G1HeapWastePercent",默认值是5%,意思是当回合回收的时候,一旦空闲出来的Region的数量达到了堆内存的5%,此时就会立即停止混合回收

FullGC

当在进行混合回收的过程中,由于无论是新生代还是老年代都是基于复制算法进行的,都需要将各个Region中的存活独享拷贝到别的Region中,此时如果一旦出现拷贝的过程中发现没有空闲的Region可以进行存储了,就会触发一次失败,那么这时候系统会立马切换为我们的Seiral收集器进行单线程标记,清理,和压缩整理,该过程就变得非常慢了

垃圾回收器总结

SerialGC

新生代内存不足发生的垃圾收集-minor Gc

老年代内存不足发生的垃圾收集 full gc

parallelGC\Parnew

新生代内存不足发生的垃圾收集 minor GC

老年代内存不足发生的垃圾收集 full gc

CMS

新生代内存不足发生的垃圾收集: minor gc

老年代内存92%开始回收,触发Concurrent Mode Failure 时触发Full GC

G1

新生代内存不足发生的垃圾收集 minor gc

老年代内存不足,无多余Region可供拷贝 触发 Full gc

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
62 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
1月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
16天前
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
1月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
43 3
|
1月前
|
存储 监控 算法
G1 垃圾回收器:底层原理与调优过程
【10月更文挑战第9天】G1(Garbage-First)垃圾回收器是Java虚拟机(JVM)中一款面向服务端应用的垃圾收集器,它在JDK 1.7中引入,并从JDK 9开始成为默认的垃圾回收器。G1的设计目标是在有限的停顿时间内,尽可能地提高系统的吞吐量,特别是在多CPU和大内存的场景下表现出色。
56 3
|
1月前
|
存储 Java Linux
【JVM】JVM执行流程和内存区域划分
【JVM】JVM执行流程和内存区域划分
42 1
|
1月前
|
监控 Java 测试技术
如何解读 jstat 工具输出的 G1 垃圾回收器性能数据?
如何解读 jstat 工具输出的 G1 垃圾回收器性能数据?
|
1月前
|
监控 Java API
如何通过监控工具来诊断G1垃圾回收器的性能问题
如何通过监控工具来诊断G1垃圾回收器的性能问题
|
2月前
|
安全 Java API
【Java炸裂更新】JDK 22:区域锚定引领G1垃圾回收革命,性能飙升新高度!
【9月更文挑战第6天】JDK 22的发布,标志着Java在性能优化和垃圾回收技术上的又一次重大突破。区域锚定技术的引入,不仅提升了G1垃圾收集器的效率,也为Java应用的性能提升注入了新的动力。随着Java生态的不断发展和完善,我们有理由相信,Java将继续在编程界保持其铁打英雄的地位,为开发者们带来更多惊喜和可能。 让我们共同期待,Java在JDK 22的引领下,开启一个全新的性能飙升时代!
79 17
|
1月前
|
监控 Java Perl
使用jstat工具来监控G1垃圾回收器的性能
使用jstat工具来监控G1垃圾回收器的性能