G1和ZGC垃圾回收器学习

前言

​ 随着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

​ 就这样吧,结束。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 全栈体系【四阶】(十五)

第五章 深度学习 一、基本理论 1. 深度学习概述 1.1 引入 1.1.1 人工智能划时代事件 2016 年 3 月&#xff0c;Google 公司研发的 AlphaGo 以 4:1 击败世界围棋顶级选手李世石。次年&#xff0c;AlphaGo2.0 对战世界最年轻的围棋四冠王柯洁&#xff0c;以 3:0 击败对方。背后…

PCB板的叠构剖析及实际案例

PCB板可以有不同的层叠结构&#xff0c;具体取决于电路设计的要求和应用的复杂性。 以下是一些常见的PCB板叠构&#xff0c;包括单层、双层和多层PCB&#xff1a; 单层PCB&#xff08;Single-Layer PCB&#xff09;&#xff1a; 基本结构&#xff1a; 单层PCB由一个绝缘性基板组…

sqllab第二十八关通关笔记(附带28a)

知识点&#xff1a; union select 整体过滤 union all select 替换where id(输入)空格 过滤了&#xff0c;使用%09代替 经过不断的测试&#xff0c;发现原始语句为 where id(输入) 构造payload:id1)and%091(1 成功回显出了相关的信息 好&#xff0c;尝试进行错误注入 构造…

理解树的结构-算法通关村

理解树的结构-算法通关村 1.树的结构 树是一个有n个有限节点组成一个具有层次关系的集合&#xff0c;每个节点有0个或者多个子节点&#xff0c;没有父节点的节点称为根节点&#xff0c;也就是说除了根节点以外每个节点都有父节点&#xff0c;并且有且只有一个。树的种类比较多…

如何自定义异常类

如何自定义异常类 为什么要使用自定义异常类&#xff1f; 在 Java 中&#xff0c;自定义异常是指用户根据自己的需求创建的异常类。Java 提供了一些预定义的异常类&#xff0c;如 NullPointerException、ArrayIndexOutOfBoundsException 等&#xff0c;但有时这些预定义的异常…

直播预告!5位大厂测开学长学姐助力你上岸测开

大家好&#xff0c;我是洋子&#xff0c;24届春招补录&25届暑期实习招聘已经进入到白热化阶段&#xff0c;近期收到了很多同学关于求职问题的咨询&#xff0c;所以开一场公益直播来为大家答疑解惑 主题&#xff1a;校招测试开发求职如何准备&职业发展 时间&#xff1…

十二、MySQL 主从复制+高可用+读写分离

目录 一、mysqlkeeplived实现高可用LVS负载均衡 一、什么是高可用 二、为什么要用高可用 三、高可用的作用 四、keeplived 是什么&#xff1f;它用在哪里 五、安装mysql以及配置主从 六、keepalived安装 1、配置 单VIP 实现高可用 master上配置 2、backup上的配置 3、…

蓝桥杯-礼物-二分查找

题目 思路 --刚开始想到暴力尝试的方法&#xff0c;但是N太大了&#xff0c;第一个测试点都超时。题目中说前k个石头的和还有后k个石头的和要小于s&#xff0c;在这里要能想到开一个数组来求前n个石头的总重&#xff0c;然后求前k个的直接将sum[i]-sum[i-k-1]就行了&#xff0…

@EnableConfigurationProperties注解使用

前言 当我们想把配置的内容,动态赋值到某个配置类上的时候,可以使用EnableConfigurationProperties ConfigurationProperties注解 代码准备 创建配置文件prop.properties nameada age18 email123qq.com 创建配置类 ComponentScan("com.test.pops") PropertySo…

天地一体化5G网络中LNA的辐射效应

Youssouf A S, Habaebi M H, Hasbullah N F. The radiation effect on low noise amplifier implemented in the space-aerial–terrestrial integrated 5G networks[J]. IEEE Access, 2021, 9: 46641-46651. 图2 面向卫星的5G综合网络架构方案 这篇论文《The Radiation Effect…

docker快速安装达梦数据库

docker快速安装达梦数据库 文章目录 docker快速安装达梦数据库前言环境准备下载镜像运行、配置容器 前言 因为公司需要将自己的底代码平台与客户的需求做适配&#xff0c;客户要求必须满足信创要求&#xff0c;使用达梦数据库。所以需要将原有的MySQL数据库与达梦数据库适配&a…

Android:adb命令

执行adb命令的窗口如下 Mac或Linux系统里的终端窗口&#xff1b; window系统运行输入cmd打开的指令窗口&#xff1b; Android Studio 里控制下面的Terminal窗口 1. 查看已链接的设备和模拟器 adb devices -l 2. 查看Android内核版本号 adb shell getprop ro.build.version.re…

面试笔记——Redis(集群方案:主从复制、哨兵模式和分片集群)

主从复制 在 Redis 主从集群中&#xff0c;一个主节点&#xff08;Master&#xff09;负责处理客户端的读写请求&#xff0c;而多个从节点&#xff08;Slave&#xff09;则负责复制主节点的数据&#xff0c;并对外提供读取服务——解决高并发问题。 主节点&#xff08;Master&…

vue@2.7.16 使用less、less-loader

遇到问题&#xff0c;npm install less-loader7.3.0 --save安装好less-loader后&#xff0c;执行npm run serve 项目运行不起来&#xff0c;排查后发现在安装less-loader后就提示需要安装less&#xff0c;正确的安装应如下&#xff1a; npm install less less-loader7.3.0 --sa…

了解电子元器件商城价格变动的背后逻辑

电子元器件商城价格的变动背后存在着多种逻辑和因素&#xff0c;这些因素相互交织、相互作用&#xff0c;共同影响着价格的波动。以下是一些可能存在的背后逻辑&#xff1a; 供需关系&#xff1a; 供应量变化&#xff1a;电子元器件市场的供应量受到供应商生产能力、原材料供应…

linux内核input子系统概述

目录 一、input子系统二、关键数据结构和api2.1 数据结构2.1.1 input_dev2.1.2 input_handler2.1.3 input_event2.1.4 input_handle 2.2 api接口2.2.1 input_device 相关接口input_device 注册流程事件上报 2.2.2 input handle 相关接口注册 handle指定 handle 2.2.3 input han…

[隐私计算实训营学习笔记] 第1讲 数据要素流通

信任四基石 数据的分级分类 技术信任&#xff1a;全链路审计、闭环完成的数据可信流通体系 技术信任&#xff1a;开启数据密态时代 数据可流通的基础设施&#xff1a;密态天空计算

第3章 数据治理

思维导图 数据治理的定义&#xff1a;是在管理数据资产过程中行使权力和管控&#xff0c;包括计划、监控、和实施。 职能&#xff1a;指导所有其他数据管理领域的活动。目的&#xff1a;确保根据数据管理制度和最佳实践正确地管理数据。整体驱动力&#xff1a;确保组织可以从其…

sd卡数据不小心删除了如何恢复,sd卡中的数据不小心被删除了如何进行恢复

在现代科技快速发展的时代,SD卡已经成为我们存储和传输数据的重要工具之一。当您不小心删除了SD卡中的数据时,这种意外情况可能引起您的困惑和焦虑。那些重要的文件、无价的回忆似乎在转瞬间消失得无影无踪。面对这种突发的数据丢失问题,我深感理解。sd卡数据不小心删除了如…

Mac上轻松几步搞定Docker与Redis安装:从下载安装到容器运行实测全程指南

1、去官网下载docker 安装&#xff1a;把图标拉到应用程序即可把图标拉到应用程序即可 https://docs.docker.com/desktop/install/mac-install/ 2、docker拉取redis镜像 拉取命令&#xff0c;后面填上版本号3.2.1&#xff0c;可以看到已经成功了。 docker pull redis:3.2.1…