基于JDK17的GC调优策略

news/2025/9/30 18:54:00/文章来源:https://www.cnblogs.com/randolf/p/19121653

基于JDK17的GC调优策略

一、JVM 参数分类(三类核心参数)

JVM 参数按稳定性分为三类,不同类别对应不同使用场景和查看方式,具体如下表:

参数类别 标识符号 稳定性 查看命令 常用示例
标准参数 - 开头 所有 HotSpot 均支持,稳定 java -helpjava -? --list_modules(查看进程模块)、-verbose:gc(显示 GC 事件)、-version(查看 JDK 版本)
非标准参数 -X 开头 特定 HotSpot 支持,较稳定 java -X -Xms200M(堆初始大小)、-Xmx200M(堆最大大小)、-Xint(解释执行)、-Xcomp(编译执行)
不稳定参数 -XX 开头 版本相关,可能变更 java -XX:+PrintFlagsFinal(最终生效参数)、java -XX:+PrintFlagsInitial(默认参数) -XX:MaxHeapSize=200M(等同 - Xmx)、-XX:+UseG1GC(启用 G1)、-XX:+PrintGCDetails(打印 GC 详情,JDK8 及以前)

注意:boolean 型不稳定参数用+(设为 true)或-(设为 false)控制,如-XX:+AggressiveHeap;数字型参数直接赋值,如-XX:ActiveProcessorCount=1

二、从 RocketMQ 学习 GC 调优三部曲

RocketMQ 作为优秀开源项目,其 GC 调优思路具有通用性,核心分为三步,且针对 JDK 版本差异调整参数:

  1. 第一步:调整 JVM 内存布局

    统一设置堆和非堆内存基础大小,避免运行时内存波动。

    • JDK8 及以前:-Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m(含年轻代-Xmn);
    • JDK9 及以后(含 JDK17):-Xms4g -Xmx4g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m(取消-Xmn,因 G1 无固定年轻代)。
  2. 第二步:选择 GC 算法并定制参数

    根据 JDK 版本选择适配算法,优化 GC 性能:

    • JDK8 及以前:用 CMS(已废弃),参数如-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70
    • JDK9 及以后(含 JDK17):用 G1(默认 GC),参数如-XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30
  3. 第三步:打印 GC 日志

    便于后续分析 GC 问题,JDK9 + 统一用-Xlog替代分散参数:

    • RocketMQ 配置:-Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M

      含义:打印所有 GC 信息到指定路径,日志名含进程 ID%p和时间%t,保留 5 个文件,每个最大30MB

三、基于 JDK17 优化 JVM 内存布局

JVM 内存分为堆区(对象存储,GC 频繁)和非堆区(类信息等,GC 少),需分别定制参数:

1. 堆内存优化(核心影响 GC 性能)

堆内存大小需平衡 “对象存储量” 与 “GC 压力”,关键参数如下:

参数 作用 配置规则 / 默认值 说明
-Xms 设置堆初始大小 单位:k/K(KB)、m/M(MB)、g/G(GB);需为 1024 整数倍,>1M;默认 = 老年代 + 年轻代 等同-XX:InitialHeapSize,若后者在其后配置,以后者为准
-Xmx 设置堆最大大小 配置规则同 - Xms;默认由操作系统决定 等同-XX:MaxHeapSize服务端建议与 - Xms 设为相同值,减少临时内存申请
-XX:MinHeapFreeRatio GC 后堆最小空闲占比 默认值需通过java -XX:+PrintFlagsFinal查看 若 GC 后剩余堆 < 该比例,堆自动扩充
-XX:MinHeapSize GC 后堆最小空闲大小 与 MinHeapFreeRatio 二选一,一个按比例,一个按固定值 避免堆过度收缩导致频繁 GC

2. 非堆内存优化(稳定,变动少)

非堆内存含元空间、线程栈、代码缓存等,参数如下:

非堆区域 关键参数 作用 默认值 / 范围
元空间(Metaspace) -XX:MetaspaceSize 触发元空间 GC 的阈值 取决于平台(如 Linux 约 21MB)
-XX:MaxMetaspaceSize 元空间最大大小 无限制(建议设合理值,避免本地内存耗尽)
线程栈 -Xss 设置单个线程栈大小 Linux/Mac:1024KB;Windows:依赖虚拟内存
-XX:ThreadStackSize 等同 - Xss 配置格式:-XX:ThreadStackSize=1024k
热点代码缓存 -XX:InitialCodeCacheSize 代码缓存初始大小 取决于 JVM,无固定默认值
-XX:ReservedCodeCacheSize 代码缓存最大大小 默认 240MB;禁用提前编译时 48MB
-XX:+SegmentedCodeCache 启用代码缓存分割 JDK17 默认启用(需-XX:+TieredCompilation且最大缓存≥240MB)
AppCDS(类共享) -Xshare:dump 归档类信息到.jsa 文件 命令:java -Xshare:dump -XX:SharedArchiveFile=hello.jsa -version
-XX:SharedArchiveFile 启动时使用归档文件 命令:java -XX:SharedArchiveFile=hello.jsa -Xlog:class+load -version

四、基于 JDK17 定制 GC 参数

JDK17 已废除 CMS,主流 GC 为G1(默认)ZGC(低延迟),两者参数差异显著:

1. G1 GC(分代、并发、区域化,默认 GC)

G1 将堆分为多个 Region(Eden/Survivor/Old/Humongous),核心参数围绕 “停顿时间目标” 和 “Region 管理”:

参数 作用 默认值 / 范围 关键说明
-XX:+UseG1GC 启用 G1 GC JDK17 默认启用 适合堆内存≥6GB、STW 延迟需 < 0.5 秒的应用
-XX:G1HeapRegionSize 设置单个 Region 大小 1MB-32MB(2 的 N 次幂);默认 = 堆内存 / 2048 RocketMQ 设为 16MB(偏大,减少 GC 频率但增加单次停顿)
-XX:MaxGCPauseMillis G1 目标最大停顿时间 200 毫秒 G1 会动态调整 Region 回收策略以达标
-XX:G1ReservePercent 保留堆空闲比例(空间换时间) 10% RocketMQ 设为 25%,应对突发内存需求,避免长停顿
-XX:InitiatingHeapOccupancyPercent 触发并发标记的堆占用比 45% RocketMQ 设为 30%,更积极 GC,保障启动稳健
-XX:G1UseAdaptiveIHOP 启用 IHOP 自适应调整 true(默认启用) 前 N 次按固定比例,后自动调整(N=G1AdaptiveIHOPNumInitialSamples)
-XX:G1AdaptiveIHOPNumInitialSamples 初始固定 IHOP 的 GC 次数 3 次 仅前 3 次按 InitiatingHeapOccupancyPercent 计算
-XX:SoftRefLRUPolicyMSPerMB 每 MB 堆中软引用过期时间 1000 毫秒(1 秒) RocketMQ 未修改,若项目少用软引用可尝试调整

2. ZGC(低延迟,JDK17 稳定)

ZGC 支持 8MB-16TB 堆,停顿时间仅几毫秒,参数少且自适应,核心参数如下:

参数 作用 默认值 说明
-XX:+UseZGC 启用 ZGC 未默认(需手动启用) 低延迟优先,牺牲部分吞吐量
-XX:ZAllocationSpikeTolerance 分配峰值容忍因子 2.0 因子 3.0 表示允许当前分配率 tripe(三倍)
-XX:ZCollectionInterval 两次 GC 的最大间隔(秒) 0(禁用间隔) 设为正数强制 GC 间隔,避免堆过度增长
-XX:ZFragmentationLimit 堆最大碎片率(%) 25% 值越低,压缩越积极,CPU 消耗越高
-XX:+ZProactive 启用主动 GC true(默认启用) 应用空闲时主动 GC,降低堆占用
-XX:+ZUncommit 释放未使用堆内存 true(默认启用) 降低 JVM 内存 footprint,供其他进程使用
-XX:ZUncommitDelay 内存未使用多久后释放(秒) 300 秒(5 分钟) 平衡释放频率与内存申请成本

关键特点:ZGC无需手动调整多数参数,仅需指定-Xmx(堆最大大小),算法会自适应环境。

五、GC 日志处理(JDK8 vs JDK17)

JDK9 + 统一用-Xlog替代 JDK8 的分散参数,简化日志配置,具体对比如下:

日志需求 JDK8 及以前参数 JDK17 参数(-Xlog) 说明
打印 GC 详情 -XX:+PrintGCDetails -Xlog:gc* gc*表示打印所有 GC 相关日志
日志输出到文件 -Xloggc:路径 -Xlog:gc*:file=路径 路径可含变量(如%p= 进程 ID,%t= 时间)
日志轮转 -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m -Xlog:gc*:file=路径:filecount=5,filesize=30M JDK17 将轮转参数整合到-Xlog后,更简洁
日志包含时间 / 标签 -XX:+PrintGCDateStamps -Xlog:gc*:file=路径:time,tags time含时间戳,tags含日志标签(如 gc,heap)

RocketMQ 在 JDK17 中使用的完整配置:-Xlog:gc*:file=${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log:time,tags:filecount=5,filesize=30M

六、其他 JVM 调优小经验(远程调试)

RocketMQ 脚本中隐藏远程调试技巧,可本地 IDEA 调试远端服务器 Java 程序,步骤如下:

  1. 启动远端程序:添加调试参数,监听指定端口

    命令:java -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y com.roy.RemoteDebugTest

    • address=5005:监听端口 5005;
    • suspend=y:程序启动后阻塞,等待调试连接(生产环境设n,避免阻塞)。
  2. 本地 IDEA 配置

    • 新建 “Remote JVM Debug” 配置,设置Host=远端IPPort=5005
    • 复制 JDK9 + 调试参数:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005(适配高版本 JDK)。
  3. 启动调试:本地 IDEA 打断点,启动远程调试,远端程序即可响应断点,实现本地调试远端代码。

注意:生产环境禁用远程调试,避免程序阻塞或安全风险。

七、学习建议(JVM 调优长期积累)

  1. 重框架,轻细节:JVM 知识复杂,优先掌握 “内存布局 - GC 算法 - 参数逻辑” 框架,不纠结 “茴字多写法” 类细节,注重逻辑自洽。
  2. 形成积累习惯:JVM 知识易忘,需结合新框架(如 Spark/Flink)、新项目,每次接触新环境时梳理其 JVM 优化思路,零碎时间积累。
  3. 重表达,练输出:JVM 知识对面试 / 故障排查关键,需练习清晰传达(如用 3 分钟讲清 G1 调优逻辑),可尝试重构 JVM 基础课程,强化表达。

4. 关键问题及答案

问题 1:JDK17 中 G1 作为默认 GC,其核心设计思想是什么?RocketMQ 对 G1 的参数配置有何特点,背后的考量是什么?

答案

  1. G1 的核心设计思想:分代、并发、基于区域(Region),将堆分为多个 1MB-32MB 的 Region(Eden/Survivor/Old/Humongous),通过动态调整回收的 Region 数量,优先回收垃圾多的 Region,以满足-XX:MaxGCPauseMillis(默认 200ms)的停顿时间目标,平衡延迟与吞吐量。
  2. RocketMQ 对 G1 的配置特点及考量:
    • -XX:G1HeapRegionSize=16m:默认值为 “堆内存 / 2048”,RocketMQ 设为 16MB(偏大),考量是 “减少 GC 频率”—— 更大的 Region 可存储更多对象,降低年轻代 GC 次数,但需接受单次 GC 停顿时间略有增加,适配中间件 “高稳定、低频繁 GC” 的需求;
    • -XX:G1ReservePercent=25%:默认 10%,RocketMQ 提高至 25%,考量是 “空间换时间”—— 保留更多空闲堆空间,应对突发内存分配(如消息峰值),避免因内存不足导致的长停顿,保障消息服务稳定性;
    • -XX:InitiatingHeapOccupancyPercent=30%:默认 45%,RocketMQ 设为 30%,考量是 “更积极 GC”—— 更早触发并发标记,避免老年代 Region 快速占满导致 Full GC,尤其适合 NameServer/Broker 这类长期运行的中间件,降低内存溢出风险。

问题 2:JDK17 中非堆内存包含哪些核心区域?各区域的关键调优参数、默认值 / 范围及适用场景是什么?

答案

JDK17 中非堆内存核心区域包括元空间(Metaspace)线程栈热点代码缓存,具体参数与适用场景如下表:

非堆区域 关键参数 默认值 / 范围 适用场景
元空间 -XX:MetaspaceSize 取决于平台(如 Linux 约 21MB) 类元信息(结构、常量池)存储,当元空间超过该值触发 GC,适用于 “动态加载类多” 的场景(如 Spring Boot 应用),避免频繁 GC
-XX:MaxMetaspaceSize 无限制 设合理最大值(如 320MB,参考 RocketMQ),避免元空间无限制占用本地内存导致 OOM,适用于所有生产环境
线程栈 -Xss/-XX:ThreadStackSize Linux/Mac:1024KB;Windows:依赖虚拟内存 解决 “方法嵌套深”(如递归)或 “线程多” 的场景,若出现StackOverflowException,可适当调大(如-Xss2m
热点代码缓存 -XX:ReservedCodeCacheSize 默认 240MB;禁用提前编译时 48MB 存储高频执行的编译后代码,适用于 “热点方法多” 的服务(如 API 网关),若代码缓存满会导致编译停止,需调大该值
-XX:+SegmentedCodeCache JDK17 默认启用(需-XX:+TieredCompilation且最大缓存≥240MB) 优化代码缓存内存利用率,避免单一缓存块碎片化,适用于所有启用提前编译的场景

问题 3:RocketMQ 提炼的 “GC 调优三部曲” 具体内容是什么?该思路为何具有通用性,普通 Java 项目如何借鉴这一思路进行 GC 调优?

答案

  1. RocketMQ “GC 调优三部曲” 具体内容:

    • 第一步:调整 JVM 内存布局:先确定堆(-Xms/-Xmx)和非堆(元空间、线程栈)的基础大小,避免内存过度收缩 / 膨胀导致 GC 频繁(如 RocketMQ 设-Xms4g -Xmx4g,保证堆稳定);
    • 第二步:选择 GC 算法并定制参数:根据 JDK 版本选适配算法(JDK8 前用 CMS,JDK9 + 用 G1),并针对性调整核心参数(如 G1 的G1HeapRegionSize),平衡延迟与吞吐量;
    • 第三步:打印 GC 日志:用统一格式输出 GC 日志(JDK17 用-Xlog),便于后续通过 GCEasy 等工具分析 GC 问题(如 RocketMQ 保留 5 个 30MB 日志文件,兼顾分析需求与磁盘占用)。
  2. 通用性原因:

    该思路遵循 “先基础(内存)→再核心(GC 算法)→后监控(日志)” 的逻辑,覆盖 GC 调优的全流程 —— 内存是 GC 的基础(内存布局不合理会直接导致 GC 低效),算法是 GC 的核心(不同场景需适配不同算法),日志是 GC 调优的反馈(无日志无法验证调优效果),适用于所有 Java 应用(从微服务到中间件)。

  3. 普通 Java 项目借鉴方式:

    • 内存布局:服务端项目将-Xms-Xmx设为相同值(如 4g),元空间设-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m(参考 RocketMQ),线程栈默认 1024KB(若递归多可设 2m);
    • GC 算法:JDK17 默认用 G1,无需额外启用,仅需根据堆大小调整-XX:G1HeapRegionSize(堆 16g 时设 8m,堆 8g 时设 4m);
    • 日志配置:复制 RocketMQ 的-Xlog配置,仅修改日志路径(如-Xlog:gc*:file=/logs/app_gc_%p_%t.log:time,tags:filecount=5,filesize=30M),定期用 GCEasy 分析日志,若出现 “GC 停顿超 500ms”,再调整MaxGCPauseMillisG1ReservePercent

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

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

相关文章

成都网站建设案例单招网网站推广人员怎么算业绩

Spring Spring Cache 注释驱动的 Spring cache 缓存介绍使用 Spring 2.5 注释驱动的 IoC 功能虚拟化 libvirt kvm 虚拟机上网 – Bridge桥接KVM详解&#xff0c;太详细太深入了&#xff0c;经典Tomcat Linux机器同时运行两个tomcat点评&#xff1a;主要是那张图片的配置 Nginx …

福安 网站设计wordpress卸载插件

因个人需要&#xff0c;mkfs.ext3 但是项目中还没有这个命令 所以琢磨了半天 这里将其小记一下 在buildrootfsz中&#xff0c;需要将e2fsprogs 勾选上然后重新编译就好了 make menuconfig Target packages-> Filesystem and flash utilities-> e2fsprogs

【MC】我的世界schematic方块坐标提取转为json

前言 主包最近在搞mc广州塔灯光效果的复刻计划(请看合集),由于主包没学过着色器编程,但是目前而言,最大的问题已经转化为只要控制每个方块的灯光颜色就够了。 所以想着用three.js做个轻量化的广州塔灯光模拟器,然…

Jenkins+IIS+Bonobo.Git.Server 搭建适用dotnet开发者的小团队的devops环境

前言: 1、在一个小团队里面,可能我们既是开发(前端+后端)也是运维还是售前售后服务。我们样样都得会,但说实话,样样都不是很精!但是我们也梦,梦想着一切能像大厂那样,开发是开发,运维是运维,各司其职。作为…

电脑开机显示屏表现无信号怎么办 原因及解决方法

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

JDK17新特性梳理

JDK17新特性梳理 一、为什么JDK17生态强制升级: 业界长期 “你发任你发,我用 Java8”,但 Spring Framework 6.0+ 明确要求 Java 17+,Spring Boot 3.2+ 不仅要求 Java 17+,还需依赖 Spring Framework 6.1.1+,且仅…

数据结构学习随笔 第一章

数据结构学习随笔 第一章该内容全部引用于 《数据结构 C 语言 第二版》 严蔚敏 李冬梅 吴伟民 著绪论 只有清楚数据的内在联系,合理地组织数据,才能对它们进行有效的处理,设计出高效的算法。 1.1 数据结构研究的内容…

函数-参数+作用域

参数:定义函数时(参数常见的使用):1. def i(num)  2. def i(num1,num2 = 自己定义)  3.def i(*arg,*kwarg)调用函数时 (参数的传入):位置参数>关键字参数不定长参数:*args:调用函数时使用位置传…

怎么给网站制作二维码毕业设计做网站好的想法

互联网IT外包15年,讲述外包那些事;让您外包项目少花钱,办好事&#xff01;IT外包最大隐形成本-沟通成本&#xff1a;客户叙述大概需求,IT公司说一做一,最后开发项目细节大堆BUG,毫无用户体验感,最后项目一拖再拖,无限延期&#xff01;究其原因,客户非IT行内人,对系统功能及流程…

用 Nim 实现英文数字验证码识别

一、背景介绍 验证码识别是图像识别领域的常见任务。本文将使用 Nim 语言 编写一个简洁的工具,调用 Tesseract OCR 来实现英文数字验证码的识别。Nim 拥有接近 C 的性能,同时提供了简洁的语法和强大的标准库,非常适…

vip视频网站怎么做装饰公司网站

2020年7月21日晚&#xff0c;GOG官方宣布提供与Epic商城的集成服务&#xff0c;这也是GOG GALAXY 2.0推出以来又一次与超大型游戏平台达成的合作。现在玩家可以通过GOG GALAXY 2.0管理、安装和启动来自Epic商城的游戏。需要注意的是&#xff0c;因为这次行为是完全官方的&#…

游戏开发与网站开发哪个难wordpress注册邮件

6月9日&#xff0c;在2020阿里云线上峰会上&#xff0c;阿里巴巴集团副总裁、数据技术及产品部负责人朋新宇推出Quick Audience、Quick A两款全新产品&#xff0c;并升级Dataphin和Quick BI两款现有产品。同时&#xff0c;阿里云零售、金融、政务及互联网企业等四大行业数据中台…

思路探索:当大型语言模型遇见数据分析的现实挑战 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

抓紧上车,别再错过啦, Github 开源后台管理平台,Naive UI !!!

嗨,我是小华同学,专注解锁高效工作与前沿AI工具!每日精选开源技术、实战技巧,助你省时50%、领先他人一步。👉免费订阅,与10万+技术人共享升级秘籍!naive-ui-pro 是一套完全免费的企业级中后台系统模板,基于 V…

顺德高端网站招商码头无忧查询系统

foreach函数是PHP中用于遍历数组或对象的函数&#xff08;且仅用于数组的遍历&#xff09;。它允许循环遍历数组中的每个元素&#xff0c;并对每个元素执行相同的操作。foreach语句的基本语法如下&#xff1a; foreach ($array as $value) {//执行的操作 }在这个语法中&#x…

惠州附近做商城网站建设哪家好做外贸的怎么建立自己的网站

sprintf()函数 这个函数在 stdio.h中&#xff1b;可以将格式化的数据写入到一个字符串缓冲区中。 int sprintf(char *str, const char *format, ...);str&#xff1a;指向字符数组的指针&#xff0c;即用于存储格式化后字符串的缓冲区。format&#xff1a;格式化字符串&#…

实用指南:电子电气架构 --- 智能座舱域环境感知和人机交互系统

实用指南:电子电气架构 --- 智能座舱域环境感知和人机交互系统pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Co…

【机器学习】朴素贝叶斯法 - 实践

【机器学习】朴素贝叶斯法 - 实践2025-09-30 18:28 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !impor…

网站开发 承接wordpress modernizr

作者&#xff1a;黄天元&#xff0c;复旦大学博士在读&#xff0c;热爱数据科学与开源工具&#xff08;R&#xff09;&#xff0c;致力于利用数据科学迅速积累行业经验优势和科学知识发现&#xff0c;涉猎内容包括但不限于信息计量、机器学习、数据可视化、应用统计建模、知识图…

汾阳网站建设用ps网站首页怎么做

文章目录 Dubbo的发展背景单一应用架构垂直应用架构分布式服务架构流动计算架构 RPCRPC的简单原理 DubboDubbo是什么Dubbo作者Dubbo的发展历程Dubbo架构 Dubbo发音&#xff1a; |ˈdʌbəʊ| Dubbo官方网站&#xff1a;http://dubbo.apache.org/ Dubbo是阿里巴巴开发的&#…