G1和ZGC垃圾回收器学习

news2024/11/14 14:31:35

前言

​ 随着JDK17的占有率不断升高和SpringBoot3最低支持JDk17,JDK17很大概率会成为大家后续升级的一个选择,而JDK17上最重要的垃圾回收器G1和ZGC,也就显得格外重要。大家提前了解或者学习一下肯定是有用的。

​ 本篇文章也默认大家了解一些垃圾回收器的知识,也不再赘述JDK8上大家比较熟悉的垃圾回收器原理和流程。

G1垃圾回收器

​ 垃圾优先(G1)垃圾收集器针对多处理器机器,可扩展到大量内存。它试图以高概率满足垃圾收集暂停时间目标,同时实现高吞吐量,几乎不需要配置。G1旨在使用当前目标应用程序和环境提供最佳的延迟和吞吐量平衡,其特点包括:

  • 堆大小可达数十GB或更大,其中超过50%的Java堆被实时数据占用。
  • 对象分配和提升的速率可能会随时间变化而显着变化。
  • 堆中存在大量碎片。
  • 可预测的暂停时间目标不超过几百毫秒,避免长时间的垃圾收集暂停。

​ 这在应用程序运行时使用一个或多个垃圾收集线程时最为明显。因此,与吞吐量收集器相比,虽然G1收集器的垃圾收集暂停时间通常要短得多,但应用程序的吞吐量也稍微较低。

​ 上面就是官网对于G1的介绍,不难看出G1有几个特点。适合大内存、几乎不需要配置、可以预测STW时间、吞吐量要略低。

内存布局

​ G1的内存布局和之前的有一些不太一样,但是还是保留了垃圾分代的特点。内存布局如下图:

jsgct_dt_004_grbg_frst_hp

G1将内存分为不同的region,每个region大小相同。其中主要包含了四种不同的区域。年轻代Eden(图中未标字母的红色区域)、幸存者区域Suivivor(图中标有S的区域)、老区域Old(图中未标字母的蓝色区域)、大对象区域Humongous(图中标H的大块区域)。

回收流程

​ G1回收流程主要是两个阶段交替。young-only阶段和Space-reclamation阶段(也叫混合GC)。具体的交替图如下:

jsgct_dt_001_grbgcltncyl

  1. young-only阶段是只处理年轻代的一个阶段,包含了以下流程。
  • Concurrent Start:这种类型的收集在执行普通的年轻代收集的同时,还开始了标记过程。并发标记确定了老年代区域中当前可达(活动)的所有对象,以便在接下来的空间回收阶段保留这些对象。标记过程在两个特殊的停顿中完成:Remark和Cleanup。并发启动暂停还可能确定是否要继续Remark阶段,在这种情况下,会发生一个短暂的并发标记撤销阶段,然后继续进行年轻代阶段。同时,在这种情况下,不会发生Remark和Cleanup。要注意,本阶段类似CMS垃圾回收器的并发标记,不会产生STW。
  • Remark:这个阶段会STW,执行引用处理和类卸载,回收完全空的区域并清理内部数据结构。在Remark和Cleanup之间,G1会计算信息,以便稍后能够并发地回收选定的老年代区域中的空闲空间,这将在Cleanup阶段中完成。
  • Cleanup:这个阶段也会STW,同时,该阶段也决定是否实际进行Space-reclamation阶段。如果后续需要进行Space-reclamation阶段,young-only阶段将以一次准备Space-reclamation阶段回收为结束。
  1. Space-reclamation阶段会伴随多次young-only阶段,除了年轻代区域外,还会疏散一组老年代区域中的活动对象。这些收集也称为混合收集。当G1确定疏散更多的老年代区域不会产生足够的空闲空间时,Space-reclamation阶段结束。

备注:

  • young-only阶段可能不会进行垃圾回收,如果计算垃圾回收的耗时远小于设定的值,会积攒多次最后一块垃圾回收。
  • young-only阶段只会回收年轻代区域和大对象区域,Space-reclamation阶段不仅包含了这两个,还有老年代区域。
  • G1的区域回收是使用复制算法,将region内的数据整理后复制到新的region中,当前region直接清除。
  • 如果G1尝试垃圾收集后,内存还是很紧张,以至于无法找到多余的空间进行复制迁移时,会触发Full GC,这种GC是单线程的,会很慢。

​ 上面的流程可能一部分知识有误,因为能力有限,翻译过来也存在一些不通的情况。欢迎大家指正。

参数和最佳实践

​ G1的一些重要参数如下:

Option and Default ValueDescription
-XX:MaxGCPauseMillis=200最大暂停时间的目标。
-XX:GCPauseTimeInterval=<ergo>最大STW间隔的目标。默认情况下G1不设定任何目标,允许G1在极端情况下连续执行垃圾收集。
-XX:ParallelGCThreads=<ergo>垃圾收集暂停期间的最大并行工作线程数。这个数值是根据虚拟机所在计算机上可用的线程数量来确定的:如果可用于进程的CPU线程数小于或等于8,则使用该数量。否则,将大于8的线程数的五分之八加到最终的线程数中。
在每次暂停开始时,最大使用的线程数还受到其他参数限制:G1不会使用超过-XX:HeapSizePerGCThread的线程数
-XX:ConcGCThreads=<ergo>用于并发工作的最大线程数。默认情况下,该值为-XX:ParallelGCThreads除以4。
-XX:+G1UseAdaptiveIHOP
-XX:InitiatingHeapOccupancyPercent=45
控制初始堆占用的。默认值表明自适应已开启,并且在最初的几个收集周期中,G1将使用老年代45%的作为标记开始阈值。
-XX:G1HeapRegionSize=<ergo> 堆区域的大小。默认值基于最大堆大小,并计算出大约2048个区域,然后相除得到这个值。用户指定的大小必须是2的幂次方,有效值范围为1到512 MB。
-XX:G1NewSizePercent=5
-XX:G1MaxNewSizePercent=60
年轻代的总大小,在这两个值之间变化,以当前使用的 Java 堆的百分比表示。
-XX:G1HeapWastePercent=5垃圾回收候选中允许的未回收空间。如果垃圾回收候选列表中的可用空间低于该值,G1将停止Space-reclamation阶段。
-XX:G1MixedGCCountTarget=8Space-reclamation阶段在一系列收集中的预计持续时间。
-XX:G1MixedGCLiveThresholdPercent=85在Space-reclamation阶段中,如果老年代区域的存活对象占用率高于这个百分比,那么这些区域将不会被回收。

<ergo>代表这个值需要根据实际情况做判断。

​ 官方对于G1的最佳实践没有说太多,对于一般应用的建议也是使用默认值即可,不怎么需要调整,因为一些参数会在G1运行中自我调整。使用过程中只需要按照大家的要求设置期望暂停时间和最大堆大小即可。然而大家需要知道的是:G1在默认配置中的目标既不是最大吞吐量也不是最低延迟,而是在高吞吐量下提供相对较小、均匀的暂停。并且,G1回收堆空间的机制和暂停时间控制会在应用程序线程和空间回收效率方面产生一些开销,这也就是大家常说的应用内存不大的话没必要考虑G1。

​ 如果需要应用高吞吐量,则可以通过使用或提供更大的堆来放宽暂停时间目标。如果延迟是主要要求,则修改暂停时间目标。不要设置-Xmn -XX:NewRatio等参数,因为这些参数会导致期望暂停时间失效。所以从JDK8迁移到JDK17时,要丢弃所有的参数配置,并且仅设置暂停时间目标和总体堆-Xmx大小-Xms。如果不满足要求,再按照上面的表格进行一些微调。

​ 当然,JVM参数不能简单的通过一两篇博客就能设置好,具体的参数配置还是要结合GC的日志和对于应用的期望。本人这一块实践也比较少,也欢迎大家交流和指正。如果对这一部分感兴趣,可以看看oracle的调优建议。G1垃圾调优

ZGC垃圾回收器

​ 先问两个小问题:

  • ZGC中的Z代表什么意思?
  • ZGC怎么读?“zed gee see”还是“zee gee see”?

​ 我们使用的最新的JDK为17版本,ZGC还是一个初步实现的版本,并没有做分代,虽然是简单实现,但是也足够优秀。目前网络上也都是基于这个版本写的文章,但是我看到2023年JVM语言峰会上,JDK21上的ZGC已经是较为完善的版本了,所以本次也就直接学习JDK21版本的ZGC,不再讲述低版本的ZGC。

​ 新版本的ZGC更加的强大,并且主打的就是更强,更智能,基本不需要参数的调整。下面是我整理的一些特点。

  • 支持最大16TB的堆。
  • 低延迟一毫秒到几毫秒。
  • 简单的配置(几乎不需要配置)。

​ 同时,新版本相较于ZGC的老版本也有很大的提升,具体可以看下图:

​ 可以说,吞吐量是之前的4倍,并且内存减少了75%。所以分代ZGC是未来的趋势。

内存布局

​ 内存布局和之前的ZGC不太一样,不再按照大小区分region,和G1类似,直接分为两种类型,年轻代和老年代。

image-20240306170709287
回收流程

​ 新版ZGC的运行流程如下图:

image-20240306171803976
  • 第一阶段就是并发标记,同时,这一阶段也会对上一个周期的移动的对象的引用进行重新映射。
  • 并发标记结束后会有一个STW,然后就是准备并发搬迁。这个准备阶段也会做一些类卸载的操作。
  • 最后就是并发迁移。

​ 同时,年轻代和老年代的回收也是并发的,ZGC这个版本可以说一个并发垃圾回收器。

image-20240306174428198

备注:

参数配置和实践

​ 使用分代的ZGC,需要使用下面的参数:-XX:+UseZGC -XX:+ZGenerational,只使用ZGC,可以配置为:-XX:+UseZGC

​ ZGC的参数很少,几乎不需要配置。

  • 不需要设置年轻代的大小,这个计算太复杂,并且要很有经验才能估算出一个大概值,ZGC自己做了。
  • 也不需要设置内存的回收阈值(就算堆内存满了,也可以使用原地压缩,进行原地复制,所以不会想G1出现回收失败的情况,导致Full GC)。
  • 也不需要设置年轻代多长时间转换到老年代。不同的阶段可能这个值是变化的,ZGC也帮我们做了。
  • 什么时候开始老年代的收集?这个成本模型计算很复杂,ZGC也不需要我们做了。
  • 回收时使用多少线程?ZGC回收时能动态设置线程数,也不需要我们设置参数了。

那我们需要设置什么?只有一个参数-Xmx就是堆的大小,听起来挺不错的。

技术难点

​ 技术难点因为本人能力有限,而且JDK21版本23年才出来,所以一部分的技术难点分析需要看源码才能了解透彻。这里就是简单说一下。

  • 颜色指针

img

  • 读屏障
垃圾回收器未来展望

​ 随着JDK21引入了虚拟线程的概念,这部分的垃圾回收就变的不太好处理了。因为没法找到一个时间节点去回收所有虚拟线程的垃圾。所以有了一个新的概念,线程本地GC。

结尾

​ 本次解释了目前比较新的垃圾回收器,也简单分析了一下技术上的细节,同时对于一些未来的技术做了一个小小的展望。当然,很多都是参考一些会议上的记录,本人能力有限,可能中间一些翻译和理解有错误,也欢迎大家指正。会议的资料地址:JVMLS2023

​ 就这样吧,结束。

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

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

相关文章

【linux】进程地址空间(进程三)

目录 快速了解&#xff1a;引入最基本的理解&#xff1a;细节&#xff1a;如何理解地址空间&#xff1a;a.什么是划分区域&#xff1a;b.地址空间的理解&#xff1a; 为什么要有进程空间&#xff1f;进一步理解页表与写时拷贝&#xff1a; 快速了解&#xff1a; 先来看这样一段…

docker入门(九)—— docker网络详细介绍

docker 网络 准备工作&#xff1a;清空所有镜像和容器 docker rm -f $(docker ps -aq) docker rmi -f $(docker images -aq)docker0 网络 查看本地网络 ip addr[rootiZbp15293q8kgzhur7n6kvZ /]# ip addr# 本地回环网络 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc…

jmeter接口导入方式

curl直接导入 1、操作页面后&#xff0c;F12查看接口&#xff0c;右击接口-copy-copy as cURL 2、jmeter 工具-import from cURL&#xff0c;粘贴上面复制的curl 根据接口文档导入 1、接口文档示例如下&#xff1a; Path&#xff1a; /api/jobs/xps/exec Method&#xf…

3d画线生成模型之后最大化找不到---模大狮模型网

当你在3D建模软件中画线生成模型后&#xff0c;如果最大化找不到该模型&#xff0c;可能是因为以下几种情况导致&#xff1a; 模型位置偏移&#xff1a; 可能你在绘制线条时&#xff0c;将模型画在了视图界面之外&#xff0c;导致最大化时无法看到。尝试平移或旋转模型&#x…

东方博宜 1449. 求满足条件的数的和

东方博宜 1449. 求满足条件的数的和 这道题我苦想了很久&#xff0c;觉得2个及2个以上很难解决&#xff0c;但是后面发现&#xff0c;可以用一个变量记录次数&#xff0c;次数大于等于2就好了。 #include<iostream> using namespace std; int main() {int n ;cin >…

企业用大模型如何更具「效价比」?百度智能云发布5款大模型新品

服务8万企业用户&#xff0c;累计帮助用户精调1.3万个大模型&#xff0c;帮助用户开发出16万个大模型应用&#xff0c;自2023年12月以来百度智能云千帆大模型平台API日调用量环比增长97%...从一年前国内大模型平台的“开路先锋”到如今的大模型“超级工厂”&#xff0c;百度智能…

革新水库大坝监测:传统软件与云平台之比较

在水库大坝的监测管理领域&#xff0c;传统监测软件虽然曾发挥了重要作用&#xff0c;但在多方面显示出了其局限性。传统解决方案通常伴随着高昂的运维成本&#xff0c;需要大量的硬件支持和人员维护&#xff0c;且软件整合和升级困难&#xff0c;限制了其灵活性和扩展性。 点击…

类对象的初始化过程与方法

类初始化过程与方法 一、类对象的初始化过程 1.初始化的过程 &#xff08;1&#xff09;对象在实例化的时候需要调用构造函数&#xff0c;如果对应的构造函数调用不了&#xff0c;这个对象是没有办法实例化的。 &#xff08;2&#xff09;构造函数的执行&#xff0c;是在内…

好看的表情壁纸

不定时更新表情壁纸&#xff0c;后期支持头像&#xff0c;wx背景等&#xff0c;个人开发&#xff0c;觉得不错&#xff0c;可前往小程序或者公众号查看

深入理解模板进阶:掌握C++模板的高级技巧

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

基于springboot的员工绩效考核管理系统(含源文件)

&#xff08;源码附文章底部&#xff09; 摘 要 科学时代的发展改变了人类的生活&#xff0c;促使网络与计算机技术深入人类的各个角落&#xff0c;得以普及到人类的具体生活中&#xff0c;为人类的时代文明掀开新的篇章。本系统为月度员工绩效考核管理系统&#xff0c;是专为…

JAVA入门第一步2.0

一、JAVA中的关键字 Java中的关键字是Java编程语言中预先定义并保留的单词&#xff0c;它们具有特殊的含义&#xff0c;不能用作变量名、方法名或类名等标识符。以下是我查到的Java中的一些主要关键字&#xff1a; 由于我还在入门&#xff0c;所以所接触的关键字不多&#xf…

从0到1实现RPC | 02 RpcConsumer的远程调用

一、RPC的简化版原理如下图&#xff08;核心是代理机制&#xff09;。 1.本地代理存根: Stub 2.本地序列化反序列化 3.网络通信 4.远程序列化反序列化 5.远程服务存根: Skeleton 6.调用实际业务服务 7.原路返回服务结果 8.返回给本地调用方 二、新建一个模块rpc-demo-c…

如何真正改变自己? 《掌控习惯》

维持改变 1.心态 目标与体系&#xff0c;谁是真正通往成功的钥匙&#xff1f; 2.行动 习惯转变的3个层次 身份 你要成为谁&#xff1f; 你为成为他而幸福吗&#xff1f;过程结果 习惯的基本原理&#xff1a;要重视微小的改变 维持改变成两个方面入手 一、心态&#xff1a;忽略…

【算法刷题】Day33

文章目录 1. 最长湍流子数组题干&#xff1a;算法原理&#xff1a;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺序5. 返回值 代码&#xff1a; 2. 最长递增子序列题干&#xff1a;算法原理&#xff1a;1. 状态表示&#xff1a;2. 状态转移方程3. 初始化4. 填表顺…

详解rtklib中main函数如何配置文件

目录 Step1&#xff1a;如何给rtklib中的主函数 rnx2rtkp 传参 Step2&#xff1a;给配置选项结构体赋默认值 Step3&#xff1a;继续配置 Step4&#xff1a;寻找 main 函数参数中的 -k Step5&#xff1a;依次遍历参数 Step1&#xff1a;如何给rtklib中的主函数 rnx2rtkp 传参…

SpringBoot接口防止重复提交(AOP+Redis)

方法一&#xff1a; 若依框架的实现 【具体靠请求地址URL参数列表来判断请求是否重复】 SpingBoot接口防止重复提交_springboot接口防抖(防重复提交)的一些实现方案-CSDN博客文章浏览阅读518次。3.根据缓存键获取缓存中对象&#xff0c;如果存在&#xff0c;判断当前请求参…

156.乐理基础-和弦固定标记法(五)挂留(sus)和弦省略音(omit)和弦

如果到这五线谱还没记住还不认识的话去看102.五线谱-高音谱号与103.五线谱-低音谱号这两个里&#xff0c;这里面有五线谱对应的音名&#xff0c;对比着看 如果一章没落下&#xff0c;看到这里&#xff0c;但是看不懂什么意思&#xff0c;那就强行下看&#xff0c;看着看着指不…

【Linux操作系统】命令的运行原理

文章目录 shell命令以及运行原理Linux系列学习目录 shell命令以及运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&…

怎么选择陪诊陪护APP开发公司

随着科技的发展&#xff0c;陪诊陪护APP已经成为了人们日常生活中不可或缺的一部分。它为患者提供了便捷的陪诊服务&#xff0c;也为医护人员提供了更多的工作机会。然而&#xff0c;市场上的陪诊陪护APP开发公司众多&#xff0c;如何选择一家专业且有实力的公司成为了消费者的…