G1 GC基本逻辑


1  MixedGC基本过程
在G1GC中,有两种主要的垃圾回收过程:Young GC和Mixed GC。这两者都是为了回收堆内存中的垃圾对象,但是他们关注的区域和工作方式有所不同。

Young GC:

Young GC主要负责回收Young Generation(包括Eden区和Survivor区)。大多数新创建的对象都首先在Eden区分配,在一段时间后,如果这些对象仍然存活,它们将被移动到Survivor区或Old区。Young GC通常会频繁发生,因为大多数对象的生命周期都很短,很快就会变成垃圾可以被回收。

Mixed GC:

与Young GC不同,Mixed GC不仅回收Young Generation,还会回收部分Old Generation。Mixed GC发生的条件是在并发标记周期结束后,也就是说,它会在完成全堆的并发标记之后进行。在Mixed GC中,G1GC会选择一些可以回收的老年代区域进行清理,这样可以在不进行Full GC的情况下,尽可能地清理掉一些长时间存活的垃圾对象

在G1GC中,实际上只有YoungGC. 或者说MixedGc是跟随YoungGC
1 Mixed GC触发条件:

1)如果堆内存的使用率超过了一个阈值(默认是45%,可以通过-XX:InitiatingHeapOccupancyPercent参数进行调整),那么将会启动一个并发周期,而Mixed GC则在并发周期结束后开始。
2)老年代的区域已经满了。G1GC会尽可能地避免Full GC,所以当老年代的区域已经满了,并且并发标记已经完成,G1GC会触发Mixed GC以回收老年代的部分区域
   老年代的使用率达到 -XX:G1OldCSetRegionThresholdPercent 参数设置的阈值,G1 GC 将会尽管不满足 G1HeapWastePercent 的要求,也会强制执行 Mixed GC,以防止老年代填满导致 Full GC


MixedGC阶段:
1)初始标记阶段
这个过程需要进入Stop the World的,仅仅只是标记一下GC Roots直接能引用的对象,这个过程速度是很快的。如下图,先停止系统程序的运行,然后对各个线程栈内存中的局部变量代表的GC Roots,以及方法区中的类静态变量代表的GC Roots,进行扫描,标记出来他们直接引用的那些对象
 
2)并发标记阶段
这个阶段会允许系统程序的运行,同时进行GC Roots追踪,从GC Roots开始追踪所有的存活对象,并对这个过程对象的变化做记录,比如哪些对象失去了引用,哪些对象是新建的。如下图所示。(这个阶段也是很耗时的,要追踪全部存活的对象,但跟系统并发运行,影响不大)

3)最终标记阶段
这个阶段会进入Stop the World,系统程序是禁止运行的,但是会根据并发标记阶段记录的那些对象修改,最终标记一下有哪些存活对象,有哪些是垃圾对象。

4)混合回收阶段

   计算存活对象数量:在并发标记阶段,垃圾收集器会遍历对象图并标记存活对象。这个过程可以帮助G1GC了解每个区域的存活对象数量。
   计算回收收益:根据每个区域的存活对象数量,G1GC会计算回收收益,即回收某个区域可以释放多少空间。
   选择回收集合:在计算完回收收益后,G1GC会根据预设的暂停时间目标(例如通过-XX:MaxGCPauseMillis参数设置)来选择哪些区域应该被包含在回收集合中。这个过程中,G1GC会优先选择回收收益较高的区域。

   这个阶段G1允许多次执行混合回收,也就是说先停止系统工作,执行回收,恢复系统运行,再停止系统运行,再回收,再恢复…这么一个流程。每次回收的间隔是由G1自己控制的,回收执行次数可以通过参数-XX:G1MixedGCCountTarget来设置,这个参数默认回收次数是8次,同时有一个参数-XX:G1HeapWastePercent,默认值是整个堆大小5%,就是说当前回收集合内即将空出来的区域大于整个堆的5%,就会立即停止混合回收了。正常默认回收次数是8次,但是可能到了4次,发现空闲Region大于整个堆的5%,就不会再进行后续回收了。
   G1HeapWastePercent参数(默认5%),控制了回收集合内总的region的内存大小,
         设置太大,
              则经过可能最多8次后还是达不到条件这个阈值。这可能会导致垃圾回收的暂停时间变长,对应用程序的响应时间产生影响。
              同时,如果 G1 GC 将这种回收效益不高的 region 也加入到回收集合(CSet)中,虽然能回收一些垃圾,但大部分空间仍然被活动对象占据,该 region 的空间利用率并未显著提高。
                   而实际上这些 region 的可回收空间并不多,这就造成了空间的浪费。也导致额外的 CPU 时间被用于回收这些 region
              如果内存使用效率较低,可能间接导致内存使用率较快达到 IHOP 阈值  InitiatingHeapOccupancyPercent,从而导致频繁触发并发标记。
         设置太小,
               导致mixed gc 很快就结束。进而导致很多需要回收的region得不到回收,也会影响内存里利用率。能使堆内存使用率更容易达到 -XX:InitiatingHeapOccupancyPercent(IHOP)阈值,从而触发更频繁的并发标记。
                如果堆空间使用率持续上升,可能会触发 Full GC,从而导致更长的垃圾收集暂停时间。
                
                
   如果发现老年代中可回收的对象不足以满足预设的暂停时间目标(由 -XX:MaxGCPauseMillis 参数设置):
   G1 GC 可能会提前结束 Mixed GC 状态,避免不必要的工作,因为继续执行 Mixed GC 可能无法释放足够的空间,却会消耗更多的 CPU 时间。
   
        a)通常是指老年代中可以被回收并释放的对象数量不足,也就是说,老年代中的大部分对象都还被程序所使用,无法被回收。
        b)也可能是短寿命的对象,这些对象在年轻代就被回收了,而长寿命的对象(通常会被分配到老年代)相对较少。 

  当老年代中可回收的对象超过预设的暂停时间,G1 GC 会提前结束 Mixed GC,避免回收时间过长,以尽量满足预设的暂停时间目标。
  但是,如果经常发生, 这可能导致老年代中未回收的对象增加,从而降低堆内存的使用效率。
  如果经常出现这种情况,可能需要调整 G1 GC 的配置参数或优化应用代码以减少老年代中的可回收对象。例如,可以增加-XX:G1OldCSetRegionThresholdPercent和-XX:G1HeapWastePercent的值,以允许 G1 GC 在 Mixed GC 阶段回收更多的老年代 Region,或者优化应用代码以减少长寿命对象的生成。
 

对于已经被加入到 Collection Set (CSet) 中的 region,无论它们是年轻代的还是老年代的,G1 GC 都会在当前的 GC 周期中进行回收。    如果没有可回收对象,则直接转YoungGC.


2     G1GC 新生代是动态的:
-XX:G1NewSizePercent和-XX:G1MaxNewSizePercent,分别为新生代比例的设定数值的下限和上限,默认值分别为5%和60%。G1会根据实际的GC情况(主要是暂停时间)来动态的调整新生代的大小,主要是调整Eden Region的个数。

以下是 G1 GC 动态调整新生代大小的几个重要因素:

暂停时间目标:G1 GC 通过 -XX:MaxGCPauseMillis 参数设置暂停时间目标。为了尽量满足这个目标,G1 GC 可以根据前几次垃圾收集的数据,动态地调整新生代的大小,以影响下一次垃圾收集的暂停时间。

应用程序行为:G1 GC 会根据应用程序的行为,如对象分配速率和对象存活率,动态地调整新生代的大小。对于分配密集型的应用,G1 GC 可能会增大新生代的大小以容纳更多的对象。对于对象存活率高的应用,G1 GC 可能会减小新生代的大小以避免存活对象过多导致的复制成本。

并发标记:G1 GC 会尽量在并发标记阶段结束后立即触发一次 Mixed GC。为了保证并发标记能够在合适的时间结束,G1 GC 会根据堆内存使用率和历史数据,动态地调整新生代的大小。

因此,新生代的动态性是 G1 GC 实现可预测的停顿时间和高吞吐量目标的一个重要方式。

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

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

相关文章

跟着GPT学设计模式之建造者模式

Builder 模式,中文翻译为建造者模式或者构建者模式,也有人叫它生成器模式。允许你创建不同口味的对象同时避免构造器污染。当一个对象可能有几种口味,或者一个对象的创建涉及到很多步骤时会很有用。 现实世界例子:想象一个角色扮…

Vue:用IDEA开发Vue,标签语法爆红问题处理

一、场景描述 我在IDEA中,学习Vue课程。 入门学习时,是在html文件中,script引入vue.js文件方式。 此时,在html文件中用v-标签,爆红。 二、解决办法 打开 菜单栏 File - Settings 选择 Editor - Files Type&#xf…

《每天一个Linux命令》 -- (5)通过sshkey密钥登录服务器

欢迎阅读《每天一个Linux命令》系列!在本篇文章中,将介绍通过密钥生成,使用公钥连接管理服务器。 概念 SSH 密钥是用于安全地访问远程服务器的一种方法。SSH 密钥由一对密钥组成:公钥和私钥。公钥存储在远程服务器上,…

软件工程复习

一、题型 单项选择题 20分 填空题 10分 判断题 10分 简答题 18分 应用题 12分 综合题 30分 软件程序数据文档 软件是无形的、不可见的逻辑实体 20世纪60年代末爆发软件危机 软件危机是指软件在开发与维护过程中遇到的一系列严重的问题 …

理解 GET、POST、PATCH 和 DELETE 请求的参数传递方式

理解 GET、POST、PATCH 和 DELETE 请求的参数传递方式 本文将向您介绍在使用 GET、POST、PATCH 和 DELETE 请求时如何传递参数。通过详细解释每种请求的参数传递方式和示例代码,您将了解如何正确地将数据发送到服务器并与之交互。 GET 请求的参数传递方式 在 GET…

CentOS 7.9安装宝塔面板,安装gitlab服务器

docker安装方式比较慢,安装包1.3GB 安装后启动很慢 docker logs q18qgztxdvozdv_gitlab-ce-gitlab-1 docker ps docker exec -it q18qgztxdvozdv_gitlab-ce-gitlab-1 sh cd /etc/gitlab cat initial_root_password 软件商店安装方式,失败了2023.12…

clickhouse删除partition分区数据

clickhouse分布式表tencent_table_20231208_DIST,本地表tencent_table_20231208_local; 30台clickhouse存储服务器; 本地表:tencent_table_20231208_local CREATE TABLE tencent_sz.tencent_table_20231208_local (id Int64 DEFA…

hook其他调试技巧

输出堆栈信息 通过 android.util.Log 输出当前线程的堆栈跟踪信息。 function showStacks() {Java.perform(function () {console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new() )); }) } 可以在需要的…

机器学习--稀疏学习

前置知识: 通常学习一次模型的过程如下:我们普遍为了获取更好的模型效果,直接对原始数据学习,会造成过拟合、需要特征提取; 而若特征提取完后依旧有很多特征,还是会容易过拟合。这时候就需要特征降维和特…

[leetcode 前缀和]

525. 连续数组 M :::details 给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。 示例 1: 输入: nums [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。示例 2: 输入: nums [0,1,0] 输出: …

笙默考试管理系统-MyExamTest----codemirror(48)

笙默考试管理系统-MyExamTest----codemirror(48) 目录 笙默考试管理系统-MyExamTest----codemirror(48) 一、 笙默考试管理系统-MyExamTest----codemirror 二、 笙默考试管理系统-MyExamTest----codemirror 三、 笙默考试管…

C/C++端口复用SO_REUSEADDR(setsockopt参数),test ok

端口复用最常用的用途应该是防止服务器重启时之前绑定的端口还未释放或者程序突然退出而系统没有释放端口。这种情况下如果设定了端口复用,则新启动的服务器进程可以直接绑定端口。如果没有设定端口复用,绑定会失败,提示ADDR已经在使用中——…

前端学习--React(5)

一、useReducer 管理相对复杂的状态数据 定义一个reducer函数,根据action值的不同返回不同的状态 在组件中调用useReducer并传入reducer函数和状态的初始值 事件发生时,通过dispatch函数分派一个对象,即通知reducer具体返回哪个状态对应的操…

STM32 寄存器配置笔记——USART DMA发送

一、DMA介绍 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传 输。无须 CPU 干预,数据可以通过 DMA 快速地移动,这就节省了 CPU 的资源来做其他操作。当产品对于时序要求较严格时,外设使用DMA的方式能够减…

深入了解Java 8日期时间新玩法:DateTimeFormatter与ZoneOffset的使用

推荐语 在这篇文章中,我们将深入探讨Java中的DateTimeFormatter和ZoneOffset类的功能和使用方法。这些类是在Java 8中引入的新的日期时间API的一部分,它们为我们提供了更灵活、更易用的日期和时间处理能力。尽管这些类在Java 8中已经出现,但…

ELK(六)—Filebeat安装部署

目录 一、介绍1.1特点1.2使用原因1.3结构图1.4工作流程 二、安装部署2.1下载2.2启动2.3监控日志文件2.4自定义字段 三、连接Elasticsearch四、工作原理 一、介绍 Filebeat是一个轻量级的日志和文件数据收集器,属于Elastic Stack(ELK Stack)中…

近期Chrome浏览器 不知哪个版本升级后原先http强制跳转到https,导致服务端302强制跳转到http也没反应

关于Chrome更新http强制跳转到https解决方法 近期Chrome浏览器 不知哪个版本升级后原先http强制跳转到https,导致服务端302强制跳转到http也没反应一、F12检查加载的Response Headers中有没有Non-Authoritative-Reason二、找了资料后得到解决方案:三、找…

云原生数据库是什么?它的作用是啥?

目前来说,各厂商的云原生数据库在演进路线上分成了两个略有不同的路径来解决不同的问题。 一种是各大公有云厂商选择的,优先保证上云兼容性的路线,就是基于存算分离架构对传统数据库进行改造的路线:通过把大量的日志操作放到后台…

插入排序——直接插入排序和希尔排序(C语言实现)

文章目录 前言直接插入排序基本思想特性总结代码实现 希尔排序算法思想特性总结代码实现 前言 本博客插入排序动图和希尔排序视频参考大佬java技术爱好者,如有侵权,请联系删除。 直接插入排序 基本思想 直接插入排序是一种简单的插入排序法&#xff…

图空图床图片外链系统源码-支持自定义权限策略-图片大小格式

含视频搭建教程。 大致功能: 支持本地等多种第三方云储存 AWS S3、阿里云 OSS、腾讯云 COS、七牛云、又拍云、SFTP、FTP、WebDav、Minio多种数据库驱动支持,MySQL 5.7、PostgreSQL 9.6、SQLite 3.8.8、SQL Server 2017支持配置使用多种缓存驱动&#xff…