JDK17强制使用-Xlog替代所有旧GC日志参数,基础配置为-Xlog:gc*:file=gc.log:time,tags,需注意路径权限、变量引号包裹、单位大小及G1/ZGC日志语义差异。

用 -Xlog 替代所有旧参数
JDK17 不再支持 -XX:+PrintGCDetails、-XX:+PrintGCDateStamps 这类分散参数。强行加进去会直接报错:Unrecognized VM option。统一日志系统从 JDK9 就已引入,到 JDK17 已是唯一正解,没有兼容路径可走。
-Xlog 基础写法与必填字段
最简可用配置是:-Xlog:gc*:file=gc.log:time,tags。其中:
-
gc*表示启用所有 GC 相关日志(含 heap、metaspace、safepoint 等子类) -
file=gc.log指定输出文件,不写则默认打到 stdout -
time输出毫秒级时间戳(推荐用utctime或uptimemillis,避免时区混淆) -
tags显示日志来源标签(如gc,heap,ref),排查时能快速定位模块
线上服务建议加上滚动策略,例如:-Xlog:gc*:file=gc.log:utctime,uptimemillis,level,tags:filecount=5,filesize=64m。
常见踩坑点:路径、权限与变量扩展
日志路径若含变量(如 %p 表示进程 ID、%t 表示启动时间),必须用双引号包裹整个 -Xlog 参数,否则 shell 会提前解析或报错:
- ❌ 错误写法:
-Xlog:gc*:file=/var/log/app/gc_%p.log:time - ✅ 正确写法:
-Xlog:gc*:file="/var/log/app/gc_%p_%t.log":utctime,uptimemillis,tags - 确保 JVM 启动用户对目标目录有写权限,否则日志静默失败,连
stderr都不报 -
filesize单位是字节,64m表示 64MB,不是 64KB —— 写错会导致日志文件极小、频繁轮转
G1 和 ZGC 日志差异不大,但关键字段含义变了
-Xlog 输出格式统一,但不同 GC 的日志内容重点不同:
- G1 日志里频繁出现
GC(123) Pause Young (Normal)或Pause Full,关注Young: 123M->45M(800M)这类内存变化 - ZGC 日志里看不到 “Pause” 字样,而是
GC(123) Concurrent Mark、Relocate等阶段,停顿时间藏在Phases小节的UpdateRemSet、FinalizeMark后面 - 所有 GC 的
Metaspace回收都会打在同一条日志流里,别漏看metaspace标签行 —— 很多OutOfMemoryError: Metaspace就是从这里先露头的
日志本身不带颜色、不自动归类,想高效分析就得靠 grep 或专用工具(比如 GCViewer、gceasy.io),别指望人眼扫完一屏就定位问题。


















