jdk 17+ 废弃 -xloggc,须改用 -xlog:gc*=info:file=... 统一日志框架,配合 time,uptime,pid,tid,level,tags 装饰器及 filecount/filesize 实现轮转,旧参数会导致启动失败。

Java 8 的 -Xloggc 在 JDK 17+ 直接失效
直接把 -Xloggc:/path/gc.log 拷到 JDK 17 或更高版本启动命令里,JVM 启动会报错:Unrecognized VM option '-Xloggc:/path/gc.log'。这不是拼写错误,而是 OpenJDK 从 9 开始彻底废弃了这套 GC 日志参数体系,统一收归 -Xlog 框架管理。旧参数不仅不生效,还会阻断 JVM 启动。
-Xlog:gc 替代方案与关键装饰器组合
等效于旧版 -Xloggc + -XX:+PrintGCDetails + -XX:+PrintGCDateStamps 的最小可用配置是:
-Xlog:gc*=info:file=/var/logs/gc-%p-%t.log:time,uptime,pid,tid,level,tags:filecount=10,filesize=50M
说明:
-
gc*=info表示启用所有 gc 相关 tag(如gc,gc+heap,gc+metaspace),级别为info(对应旧版PrintGCDetails的详细程度) -
file=/var/logs/gc-%p-%t.log中%p是进程 PID,%t是启动时间戳,避免多实例日志覆盖 -
time,uptime,pid,tid,level,tags是常用装饰器,提供可读性——缺省时日志只有原始事件,没有时间戳或线程 ID -
filecount=10,filesize=50M实现轮转,替代旧版-XX:+UseGCLogFileRotation等三连配置
常见踩坑:日志没内容、文件不轮转、权限被拒
迁移到 -Xlog 后发现日志为空、只生成一个超大文件、或启动失败报 Permission denied,多半是以下原因:
- 路径不存在且父目录无写权限:
/var/logs/往往需要 root 创建并赋权,普通用户启动时建议改用应用有写权限的路径,如./logs/gc.log - 忘记加
file=输出目标:只写-Xlog:gc默认输出到stderr,容器里会被混进应用日志流,查 GC 问题时根本找不到 - 误用旧版轮转参数:
-XX:NumberOfGCLogFiles在 JDK 17+ 完全无效,继续保留会导致 JVM 忽略整个-Xlog配置甚至启动失败 - 过度开启 tag 导致性能抖动:比如
-Xlog:gc+ref=debug在高并发引用频繁场景下会产生海量日志,建议生产环境保持info级别,调试时再升debug
G1/ZGC 场景下要额外加的 tag
如果你已切换到 G1 或 ZGC,仅 gc tag 不足以定位典型问题。需按需叠加:
- G1 延迟超标?加
gc+ergo=debug查 JVM 自适应调优决策,比如为什么没满足-XX:MaxGCPauseMillis - ZGC 出现
Allocation Stall?必须加gc+alloc=debug,否则日志里看不到对象分配卡点 - 怀疑元空间泄漏?补上
gc+metaspace=info,和gc+class+unload=info联用看类卸载是否正常 - 想确认是否真用了 ZGC?启动后执行
jcmd PID VM.flags,检查输出中是否有-XX:+UseZGC,不能只信-Xlog参数名
真正容易被忽略的是:日志路径里的 %p 和 %t 只在 JVM 启动时展开一次;如果应用热重启(如 Spring Boot DevTools),新进程仍会写入旧文件名——这不是 bug,是设计使然,得靠外部脚本或日志收集器(如 filebeat)做二次区分。











