最可靠的方法是用 java -xx:+printcommandlineflags -version 查 jvm 默认 gc 参数,它直接反映当前 java 可执行文件的默认回收器,如 +useg1gc 表示启用 g1;再结合 jinfo -flags、jstat -gc 和 garbagecollectormxbean 多维度验证实际生效配置。

直接看 JVM 启动时实际生效的 GC 参数,比查文档或猜版本更可靠。OpenJDK 没有统一“默认值”——它取决于具体版本、运行模式(client/server)、是否被显式配置过,甚至某些构建变体还会微调。
用 java -XX:+PrintCommandLineFlags -version 查默认启动参数
这是最轻量、最通用的方法,不需要 Java 进程正在运行:
- 执行
java -XX:+PrintCommandLineFlags -version,输出里会有一行类似-XX:+UseG1GC或-XX:+UseParallelGC的标记 - 只要看到
+UseXXXGC(带加号),就表示该回收器被启用;-UseXXXGC(带减号)表示被显式禁用 - JDK 17+ 多数构建默认输出
+UseG1GC;JDK 8u 早期版本常见+UseParallelGC;JDK 21+ ZGC 默认未启用,需手动加-XX:+UseZGC - 注意:这个命令只反映 当前 java 可执行文件的默认行为,不包含你项目里额外加的 JVM 参数
用 jps + jinfo -flags 查运行中进程的实际配置
适用于已启动的 Java 应用,能反映真实生效的参数:
- 先运行
jps -l获取目标进程 ID(比如12345) - 再执行
jinfo -flags 12345,搜索输出中的UseG1GC、UseParallelGC等关键词 - 如果输出里没出现任何
Use.*GC,说明 JVM 没有显式启用某回收器——此时它会按自身规则 fallback 到隐式默认值(例如 JDK 8 Server 模式 fallback 到UseParallelGC) - 注意:
jinfo在部分安全加固环境或容器中可能被禁用,且 JDK 17+ 默认关闭了 Attach API,需确保启动时加了-XX:+StartAttachListener
用 jstat -gc 从行为反推回收器类型
当无法读取参数(如权限受限、容器无 jdk 工具)时,靠 GC 日志特征判断:
- 运行
jstat -gc <pid></pid>,观察列名:
– 出现PSYoungGen/ParOldGen→ Parallel GC
– 出现G1YoungGen/G1OldGen→ G1 GC
– 出现S0C/S1C/EC/OC(无前缀)→ Serial GC 或 CMS(CMS 已在 JDK 14 移除) - 搭配
jstat -gcutil <pid> 1000</pid>(每秒刷新)看 GC 频率和停顿分布:G1 倾向小而频繁的 pause;Parallel GC 停顿长但次数少;ZGC 几乎不可见停顿 - 此方法是间接推断,不能 100% 确认——比如
ParOldGen只说明老年代用了 Parallel Old,但新生代可能是 ParNew 或 PSYoungGen,需结合其他线索
用 Java 代码通过 GarbageCollectorMXBean 获取运行时信息
适合嵌入到应用内部做自检或监控上报:
- 调用
ManagementFactory.getGarbageCollectorMXBeans(),遍历每个GarbageCollectorMXBean的getName() - 典型名称映射:
–PS Scavenge+PS MarkSweep→ Parallel GC
–G1 Young Generation+G1 Old Generation→ G1 GC
–ZGC→ ZGC(JDK 15+)
–Shenandoah→ Shenandoah(需独立启用) - 注意:
getName()是 JVM 实现相关字符串,不同厂商/版本可能略有差异;且某些回收器(如 ZGC)在未触发 GC 前可能不会出现在列表中 - 这个方式能拿到实时 GC 次数和耗时,但不能替代参数检查——比如
UseZGC被设为 true,但还没发生 GC,getGarbageCollectorMXBeans()可能只返回空列表
真正容易被忽略的是:JVM 参数之间存在互斥关系。比如同时指定 -XX:+UseG1GC 和 -XX:+UseParallelGC,后者会被前者静默覆盖,但 jinfo -flags 仍会显示两者——必须看最终生效的那个 + 标记。别只扫一眼就下结论。











