JVM学习日记(十)Day10

G1回收器

这一篇是详细说明G1回收器的,因为他相对来说确实是个缝合怪,上篇的内容又太多了所不清楚,所有这一篇进行详细的说明,

第一个呢就是其实G1是兼顾并行和并发的,简单来说就是既可以并行也可以并发,最大程度利用系统资源,在实现可达的最大吞吐量的前提下,尽可能的减少STW的时间,简单的流程就是执行GC会先STW,然后多线程执行标记或者回收实现并行,然后切换回用户线程,实现并发。

第二个就是分代分区的不同,上一篇主包有说过G1使用了分区算法把内存分成小的区域Region,但是分代其实和其他的回收器是不同的,他没有像其他区一样很严格的进行年轻代和老年代的划分,如图:

 他是先分区再分代的,也就是年轻代和老年代的区域可以不连续的,那同学就会问怎么执行标记整理?老年代不得乱套啊,其实不会的还是和之前一样向起始地址移动。

第三种就是可预测的时间模型,因为采用了分区算法和分代算法,让年轻代和老年代的区域更加的小了,G1可以根据各个需要回收的Region来进行价值排序任何放入列表优先回收(回收的空间和回收需要的时间)。这个就比较厉害了可以在相同的时间内比其他的回收器回收的效率更高,因为可以在不同的时间里选取最优的区域进行回收。

缺点就是内存的占用是比其他任何回收器都要高的多,这也是没办法要维护的表和屏障就比其他的多多了,因为是缝合怪的缘故所以推荐使用的内存就是6GB+使用G1。

G1回收器的参数设置

基础参数:

  1. **-XX:+UseG1GC**​:启用G1垃圾回收器(必备参数)。
  2. ​**-XX:MaxGCPauseMillis:设置目标最大停顿时间(默认200ms)。G1会尝试调整堆分区(Region)大小和回收策略以达到该目标,但不保证严格满足**。这个和上面说的可预测时间模型是有关系的,如果设置的太短那么回收Region选择的就会很少,如果设置的太大又会让用户觉得卡顿。
  3. ​**-XX:GCPauseTimeInterval**​:设置GC停顿的间隔时间目标(毫秒),与MaxGCPauseMillis配合使用。字面意思就是下一次GC相隔的时间。

 堆与Region配置​:

  1. ​**-XX:G1HeapRegionSize**​:设置Region大小(1MB~32MB,需为2的幂)。默认值由堆大小自动计算(所以到Region都是相同的,设置了后直到程序结束这个过程中Region的空间是不会改变的,另外G1回收器还有个Humongous区域就是存大对象的,超过1.5个Region就放在Humongous中,而这个H区是连续的不像R一样分成很细的区域,不然一个大对象岂不是没地方放了),大Region可减少碎片但可能增加停顿时间,小的话就是相反咯增加内存碎片但是减少停顿时间。
  2. ​**-XX:InitiatingHeapOccupancyPercent(IHOP)​**​:触发并发标记周期的堆占用阈值(默认45%)。当内存占用超过此比例时,启动混合GC。
  3. **-XX:G1ReservePercent**​:保留堆空间的百分比(默认10%),用于晋升失败时的回退,避免Full GC。

 GC触发与并行度​:

  1. **-XX:ConcGCThreads**​:并发标记阶段的线程数(默认值基于CPU核心数)。过多线程可能影响应用吞吐量。
  2. ​**-XX:ParallelGCThreads**​:STW阶段(如年轻代GC)的并行线程数,默认与CPU核心数相关。
  3. **-XX:G1MixedGCCountTarget**​:混合GC的预期回收次数(默认8次),控制老年代Region的回收节奏。
  4. ​**-XX:G1HeapWastePercent**​:允许的堆浪费比例(默认5%)。当可回收空间低于此值时,停止混合GC。

 还有很多的命令这边就不一个一个去解释介绍了,有兴趣的小伙伴可以JVM实战-G1参数调优 - 鱼007 - 博客园自行查看了解。但是G1的设计初衷就是为了简化JVM的调优,一般的调整只需要三步,启用G1回收器,设置堆的最大内存,设置最大时间。

回收器和回收模式

不知道小伙伴还记不记得主包之前有提过的什么MinorGC、MajorGC、FullGC呢(JVM学习日记(二)Day2-CSDN博客)?那他们和主包上一篇讲的7大GC有什么关系呢?

其实很好理解他们的关系就是回收器和回收模式,像MinorGC指的就是回收年轻代而Serial指的就是回收器,也就是MinorGC是所以年轻代GC的代名词,而实际怎么去实现GC用什么算法是GC回收器决定的(这里提一下还有个MixedGC也就是混合GC,也是G1可以使用的,简单来说就是同时回收年轻代和老年代,但是这个是部分回收,不像FullGC全部回收)。

记忆集与写屏障

记忆集(Remembered Set, RSet)

每个Heap Region(内存分区)都有一个RSet,用于记录其他Region中的对象对本Region的引用。例如:老年代Region A中的对象引用了年轻代Region B中的对象,则Region B的RSet会记录这个引用关系(Rset记录的是谁引用了我,而不是我引用了谁)。为什么需要RSet?​​G1是基于Region的分区回收器,回收时需要知道哪些Region是存活的(避免误回收)。如果没有RSet,每次回收一个Region时,需要扫描整个堆才能确定是否有其他Region引用它,效率极低。RSet让G1可以只扫描相关Region,大幅减少GC工作量。sRSet如何实现?通常是一个哈希表或卡表(Card Table)​结构,存储引用来源的Region或卡页(Card)信息。例如:G1使用​“卡表”​​(Card Table)来粗粒度记录跨Region引用,再通过RSet细化管理。那什么又是卡表?将内存划分为固定大小的卡页,每个卡页对于卡表中的一个标记位,简单来说就是RegionA引用了RegionB中某一块内存的对象,RegionA的Rset就会记录这个被引用内存的卡页。

写屏障(Write Barrier)​

在对象引用被修改时触发,记录跨Region引用的变化到RSet。例如:当对象A(在Region 1)的字段被修改,指向对象B(在Region 2)时,写屏障会更新Region 2的RSet。为什么需要写屏障?​​在并发标记阶段,用户线程可能修改对象引用关系,导致标记结果不准确(漏标或误标)。写屏障通过捕获引用变化,保证RSet和标记结果的正确性。写屏障也分前/后写屏障,简单来说就是修改被引用对象的前/后修改引用他的Rset。

结构大概就是这样子,这个的外R地址指的是外部Region的地址哦,这个ABCDE就是这个Region中存放的区块。

外部Region地址脏卡页索引实际引用位置
0x10000000Bitmap: ...0100Region 1的卡页2(0x10001000)
0x30000000Bitmap: ...100000Region 3的卡页5(0x30002800)

 G1回收器的回收阶段

 

1. 年轻代GC(Young GC)​

触发条件​:Eden区Region占满时触发(STW)。快速回收年轻代(Eden + Survivor)。关键步骤​:

  1. 初始标记(Initial Mark)​​:短暂STW,标记GC Roots直接可达的对象(借Young GC执行)。
  2. 根区域扫描(Root Region Scanning)​​:扫描Survivor区中引用老年代的对象(需在下次Young GC前完成)。
  3. 复制存活对象(Evacuation)​​:并行将存活对象复制到Survivor区或晋升到老年代。
  4. 调整Region分配​:根据MaxGCPauseMillis动态调整Eden/Survivor的Region数量。
2. 并发标记周期(Concurrent Marking Cycle)​
  • 触发条件​:老年代占用达到InitiatingHeapOccupancyPercent(默认45%)。标记全堆存活对象,为混合GC做准备。关键步骤​:
  1. 初始标记(Initial Mark)​​:短暂STW,标记GC Roots直接可达的对象(与Young GC共用)也就是先大概全堆标记一下确定范围。
  2. 并发标记(Concurrent Marking)​​:短暂STW与用户线程并发遍历堆,标记存活对象。
  3. 最终标记(Remark)​​:短暂STW,处理并发标记期间遗漏的对象,可能上个阶段并发的时候用户线程又改变了部分对象,可能出现漏标。
  4. 清理(Cleanup)​​:统计Region存活数据,识别可回收Region(部分STW)。
 3. 混合回收(Mixed GC)​
  • 触发条件​:并发标记完成后启动。回收年轻代 + 部分老年代Region(存活率低的Region优先)。​关键步骤​:
  1. 选择回收集(Collection Set)​​:包含所有年轻代Region + 部分老年代Region(基于G1MixedGCLiveThresholdPercent,也就是对象存活率,默认65%当一个Region中存活的对象的内存占用小于这个Region的65%,这个区域会被优先收回)。
  2. 复制存活对象(Evacuation)​​:并行将存活对象复制到空闲Region(STW)。
  3. 调整策略​:根据G1HeapWastePercent(允许可浪费空间,当可回收的垃圾小于这个默认值就不好采用混合GC)决定是否继续混合回收。
 4.FULLGC

这个就不多说啦,就是内存不足的时候无法使用上面的GC了就会触发这个最后的GC,退回到单线程的Serial Old GC(完全STW,长时间停顿)。

总结

本篇主要讲的就是G1回收器,本篇内容比较多,大火们慢慢品哦。

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

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

相关文章

使用IP扫描工具排查网络问题

随着企业的发展,网络中会新增各类设备,从台式机、服务器到物联网设备和虚拟机(VMs),所有这些设备都通过复杂的子网和虚拟局域网(VLAN)相连。 这种复杂性给 IT 团队带来了压力,他们需…

Wireshark TS | 发送数据超出接收窗口

前言 来自于测试中无意发现到的一个接收窗口满的案例,特殊,或者可以说我以前都没在实际场景中见过。一开始都没整太明白,花了些精力才算是弄清楚了些,记录分享下。 问题说明 在研究拥塞控制的慢启动阶段时,通过 packet…

C语言自定义数据类型详解(四)——联合体

好的,接下来我们来学习最后一个自定义数据类型——联合体。 一、什么是联合体: 联合体又叫共用体,用关键字union来进行定义。又因为所有的成员变量共用同一段内存空间(关于这一点,我们不久就会加以验证)&…

[python][flask]Flask-Login 使用详解

1. 简介Flask-Login 是 Flask 的一个扩展,专门用于处理用户认证相关的功能。它提供了用户会话管理、登录/注销视图、记住我功能等常见认证需求,让开发者能够快速实现安全的用户认证系统。2. 安装与基础配置首先,需要安装 Flask-Login&#xf…

【WebGPU学习杂记】WebAssembly中的relaxed_madd指令到底做了什么?

relaxed_madd 这条指令到底做了什么核心&#xff1a;relaxed_madd 是一个分量级别 (Component-wise) 的操作 首先&#xff0c;最重要的一点是&#xff1a;v128.relaxed_madd<f32>(a, b, c) 不是矩阵乘法。它是一个在三个向量 a, b, c 之间进行的、逐个分量的、并行的融合…

【全新上线】境内 Docker 镜像状态监控

境内 Docker 镜像状态监控&#xff1a;您的 Docker 加速伴侣 在当今云计算和容器化技术飞速发展的时代&#xff0c;Docker 已成为开发者不可或缺的工具。然而&#xff0c;对于身处国内的用户而言&#xff0c;访问境外 Docker Hub 等镜像仓库时常会遭遇网络延迟和连接不稳定的困…

Visual Studio中部署PaddleOCRv5 (借助ncnn框架)

PaddleOCRv5_ncnn PaddleOCRv5 在Visual Studio中进行图片OCR检测&#xff08;ncnn框架open-mobile实现)&#xff0c;尝试对nihui的ncnn-android-ppocrv5检测算法的剥离与移植。 本项目Github链接如下&#xff1a;PaddleOCRv5_ncnn 写在前面 本仓库代码是基于nihui的ncnn-a…

中级全栈工程师笔试题

解释ACID特性&#xff0c;如何在node.js中实现事务操作针对React单页应用&#xff0c;请提供至少5种性能优化方案&#xff0c;并解释其原理&#xff1a; 减少首屏加载时间优化渲染性能资源加载策略状态管理优化代码分割方案 如何防止以下攻击&#xff1a; JWT令牌挟持Graph QL查…

Windows---动态链接库Dynamic Link Library(.dll)

DLL的“幕后英雄”角色 在Windows操作系统的生态中&#xff0c;有一类文件始终扮演着“幕后英雄”的角色——它们不像.exe文件那样直接呈现为用户可见的程序窗口&#xff0c;却支撑着几乎所有应用程序的运行&#xff1b;它们不单独执行&#xff0c;却承载着系统与软件的核心功…

深入分析计算机网络传输层和应用层面试题

三、传输层面试题&#xff08;Transmission Layer&#xff09;传输层位于 OSI 七层模型的第四层&#xff0c;它的核心任务是为两个主机之间的应用层提供可靠的数据传输服务。它不仅承担了数据的端到端传输&#xff0c;而且还实现了诸如差错检测、数据流控制、拥塞控制等机制&am…

【RH134 问答题】第 2 章 调度未来任务

目录crontab 文件中的用户作业时间格式怎么解释&#xff1f;如果需要以当前用户身份计划周期性作业&#xff0c;在上午 8 点到晚上 9 点之间每两分钟一次输出当前日期和时间&#xff0c;该作业只能在周一到周五运行&#xff0c;周六或周日不能运行。要怎么做&#xff1f;要计划…

【ee类保研面试】通信类---信息论

25保研er&#xff0c;希望将自己的面试复习分享出来&#xff0c;供大家参考 part0—英语类 part1—通信类 part2—信号类 part3—高数类 part100—self项目准备 文章目录**面试复习总纲****Chap2: 熵、相对熵和互信息 (Entropy, Relative Entropy, and Mutual Information)****…

vue2+node+express+MongoDB项目安装启动启动

文章目录 准备环境 安装MongoDB 安装 MongoDB Compass(图形化数据库管理工具) 安装 Postman(接口测试工具) 项目结构 配置项目代理 项目启动 提交项目 生成Access Token 准备环境 默认含有node.js、npm 安装MongoDB 下载地址:https://www.mongodb.com/try/download/com…

JavaEE初阶第十二期:解锁多线程,从 “单车道” 到 “高速公路” 的编程升级(十)

专栏&#xff1a;JavaEE初阶起飞计划 个人主页&#xff1a;手握风云 目录 一、多线程案例 1.1. 定时器 一、多线程案例 1.1. 定时器 定时器是软件开发的一个重要组件&#xff0c;是一种能够按照预设的时间间隔或在特定时间点执行某个任务或代码片段的机制。你可以把它想象成…

EDoF-ToF: extended depth of field time-of-flight imaging解读, OE 2021

1. 核心问题&#xff1a;iToF相机的“景深”死穴我们之前已经详细讨论过&#xff0c;iToF相机的“景深”&#xff08;有效测量范围&#xff09;受到光学散焦的严重制约。问题根源&#xff1a; 当iToF相机的镜头散焦时&#xff0c;来自场景不同深度的光信号会在传感器像素上发生…

符号引用与直接引用:概念对比与实例解析

符号引用与直接引用&#xff1a;概念对比与实例解析 符号引用和直接引用是Java虚拟机(JVM)中类加载与执行机制的核心概念&#xff0c;理解它们的区别与联系对于深入掌握Java运行原理至关重要。下面我将从定义、特性、转换过程到实际应用&#xff0c;通过具体示例全面比较这两类…

每日一讲——Podman

一、概念1、定义与定位Podman&#xff08;Pod Manager&#xff09;是符合OCI标准的容器引擎&#xff0c;用于管理容器、镜像及Pod&#xff08;多容器组&#xff09;。它无需守护进程&#xff08;Daemonless&#xff09;&#xff0c;直接通过Linux内核功能&#xff08;如命名空间…

Spring Boot DFS、HDFS、AI、PyOD、ECOD、Junit、嵌入式实战指南

Spring Boot分布式文件系统 以下是一些关于Spring Boot分布式文件系统(DFS)的实现示例和关键方法,涵盖了不同场景和技术的应用。这些示例可以帮助理解如何在Spring Boot中集成DFS(如HDFS、MinIO、FastDFS等)或模拟分布式存储。 使用Spring Boot集成HDFS 基础配置 // 配…

解决GoLand运行go程序报错:Error: Cannot find package xxx 问题

问题描述 一个简单的go程序&#xff0c;代码如下 package mainimport "fmt" func main() {// 占位符&#xff0c;和java的String.format用法一样fmt.Printf("我%d岁&#xff0c;我叫%s", 18, "yexindong") }结构如下当我想要运行时却报错 Error:…

Spring MVC设计精粹:源码级架构解析与实践指南

文章目录一、设计哲学&#xff1a;分层与解耦1. 前端控制器模式2. 分层架构设计二、核心组件源码解析1. DispatcherServlet - 九大组件初始化2. DispatcherServlet - 前端控制器&#xff08;请求处理中枢&#xff09;请求源码入口&#xff1a;FrameworkServlet#doGet()请求委托…