JDK 26 Generational Shenandoah 怎样选择垃圾收集模式
来源:17golang原创
时间:2026-10-21 20:44:50 250浏览 收藏
JDK 26 Generational Shenandoah 怎样选择垃圾收集模式
在包含 Shenandoah 的 JDK 26 构建中,要明确使用分代模式,应同时指定 -XX:+UseShenandoahGC 和 -XX:ShenandoahGCMode=generational。不要把“分代模式已经成为正式功能”理解为“只要启用 Shenandoah 就默认分代”:JDK 26 的 java 命令文档仍把模式默认值列为 satb。
官方地址:https://openjdk.org/
JEP 521 对应的是 JDK 25 中分代模式从实验功能转为正式功能,取消了为该模式解锁实验选项的要求。下面只讨论 JDK 26 的选择和启用条件,不把后续版本的默认值变化套到本版,也不提供未经实际业务测量的性能承诺。
为什么加了 Shenandoah 参数仍要确认模式
假设你在升级服务时保留了启动脚本中的 UseShenandoahGC,随后看到“Generational Shenandoah”介绍,便以为现有进程已经切换。这里的误判来自把两个问题合并了:当前选中了哪个收集器,以及该收集器用了哪一种模式。
排查时先抄出服务真正使用的 Java 可执行文件、完整版本和启动参数,不要只看开发终端的 java。容器镜像、服务管理脚本和本地环境可能使用不同的安装目录。再追踪参数来自哪里:镜像入口、启动脚本、平台配置或 Java 启动器环境变量。记录“配置里写了什么”和“实际进程使用什么”,二者不能互相替代。
这一轮定位的结果应是一份可说明来源的配置,而不是一句“已经升级到 26”。本文示例是供读者在自己的环境使用的命令,不是本机运行记录,也没有编造启动日志。
先区分收集器、模式与启发式
UseShenandoahGC 用于选择 Shenandoah 收集器;ShenandoahGCMode 决定其工作模式;ShenandoahGCHeuristics 则是所选模式内部的策略调节。官方 JDK 26 文档列出 satb 为单代模式、generational 为分代模式,并说明分代模式只支持 adaptive 启发式。

因此,原先脚本若有专门调过的启发式,不宜在切换模式时全部照搬。先建立只有必要参数的对照,再按对应构建文档判断旧参数是否适用。特别要避免把“默认启发式 adaptive”和“默认模式 satb”看成同一个默认设置。
| 要回答的问题 | 对应配置 | 记录方式 |
|---|---|---|
| 选择哪一个收集器 | UseShenandoahGC | 记录启用项与其他 GC 参数 |
| 选择哪一种模式 | ShenandoahGCMode | 对照时显式写出模式 |
| 如何调节所选模式 | ShenandoahGCHeuristics | 先保留适用的默认策略 |
用独立命令明确选择两种模式
下面两条命令是互相独立的候选启动方式,不能把两条中的模式参数拼在同一个进程里。app.jar 是待替换的应用文件名。这里不强行指定堆大小:对照时沿用同一套经过容量规划的堆和容器限制,避免同时引入第二个变量。
# 分代候选:显式选择收集器和模式;app.jar 换成自己的应用。 java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -Xlog:gc -jar app.jar
对于原先使用单代模式的服务,另存下面这份显式基线配置,便于识别实验组与对照组。不要因为两者都含有 Shenandoah 就用同一个配置名称覆盖保存。
# 单代基线:与分代候选分开运行,保留同一业务输入和资源限制。 java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=satb -Xlog:gc -jar app.jar
启用 GC 日志是为读者保留观察入口,不意味着看到几行 GC 信息就足以证明业务收益。先确认启动没有选项错误,再结合实际构建的日志说明、进程参数与部署记录确认选择。不要把本文示例当作某个平台必然支持的承诺。
遇到启动失败先排除构建与参数混用
如果选择项不被识别,或者启动提示收集器不可用,先看实际 Java 构建是否包含该收集器,以及启动器是不是预期版本。JDK 的版本号不能替代发行版、架构和构建说明。此时先解决支持条件,而不是添加更多调优开关来碰运气。
若配置中同时保留了其他收集器的选择项,应先消除冲突,让一份配置只表达一个选择意图。若刚从旧文章复制过参数,再核对是否混入与分代模式不相容的启发式。将完整报错保留在内部记录中,按它指向的具体选项处理,不要把所有启动失败都归结为“分代 GC 有问题”。
建议按可执行文件、构建支持、收集器选择、模式、附加选项的顺序逐项梳理。这是故障定位方法,不是要求在正式服务上逐个试错。应在隔离环境先消除启动层面的问题。
根据同条件业务观察决定是否切换
能启动只证明候选配置具备运行条件,不证明它适合你的服务。可把分代模式列为候选,把现有模式作为基线;保持应用版本、业务数据、资源额度和预热安排一致,再看业务延迟、吞吐、CPU 使用和内存压力。本文不把任一单项变化直接解释为收集器优劣。

例如平均延迟下降而尾部延迟上升时,不能只选好看的指标;吞吐上升但容器内存压力加大时,也要回到服务约束判断。先写下服务可接受的阈值,再看观察值,而不是实验结束后临时选择有利口径。
观察时间需要覆盖实际的稳定负载与波动场景。预热阶段、流量变化和应用缓存状态都可能干扰比较。缺少可比条件时,结论应是“证据不足,继续保留基线”,而不是用模式名称代替性能分析。此处是工程对照建议,不声称已经完成压测。
保留回退配置并回答常见疑问
决定试用前,保存基线启动配置、应用版本、镜像或运行环境标识。试用后若业务指标超出事先确定的范围,回退到那份经过记录的基线,再排查是否存在应用或资源变化。回退应作为一次有计划的重新部署处理,不能假定修改启动参数就能让现有进程即时换模式。
JDK 26 还要加 UnlockExperimentalVMOptions 吗?不应仅为了分代 Shenandoah 添加它;JEP 521 已将该模式转为正式功能。项目若有其他实验特性,需要按那些特性的文档单独判断。
只写 UseShenandoahGC 可以表示分代吗?对本文讨论的 JDK 26 文档规则,不可以据此作这个推断。需要明确分代意图时写出 generational,并核对实际构建。
正式功能就一定更适合生产吗?正式状态不等于对每种业务负载都占优。构建支持、应用约束、对照观察和可回退配置仍然是采用条件。
最终选择可以很朴素:明确需要试用分代时显式指定 generational,维持旧行为的对照配置显式写 satb;把模式是否启用与业务是否受益分成两项记录。
参考:JDK 26 java 命令文档;JEP 521 对应的官方兼容性说明。JDK 26 文档中的 ShenandoahGCMode 和 ShenandoahGCHeuristics 条目提供本文模式与启发式规则。
-
501 收藏
-
文章 · java教程 | 1个月前 | Java · 异常处理 · 资源管理 · java try-with-resources AutoCloseable close suppressed exception501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
441 收藏
-
181 收藏
-
211 收藏
-
485 收藏
-
190 收藏
-
114 收藏
-
492 收藏
-
134 收藏
-
158 收藏
-
241 收藏
-
345 收藏
-
279 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习