Java应用的GC日志是排查内存泄漏、GC频繁等问题的核心依据,生产环境中如果应用启动时未配置GC日志参数,传统方式需要重启应用才能开启,这会给业务带来中断风险。其实JVM提供了动态修改部分参数的能力,我们可以在不重启应用的情况下启用GC日志。

不同JDK版本的支持情况
JDK版本不同,动态启用GC日志的实现方式存在差异,主要分为JDK 8及之前版本、JDK 9及之后版本两类,两者的GC日志参数体系完全不同。
JDK 8及之前版本
JDK 8及之前的版本使用PrintGCDetails、PrintGCDateStamps等参数控制GC日志输出,这些参数属于可动态修改的JVM参数,我们可以通过JVM工具直接修改。
JDK 9及之后版本
JDK 9引入了统一的GC日志框架,使用-Xlog参数替代了之前的零散GC参数,该参数同样支持运行时动态修改,配置方式更加灵活。
JDK 8动态启用GC日志步骤
JDK 8环境下我们可以通过jinfo工具动态修改JVM参数,具体操作步骤如下:
1. 查找目标Java进程PID
首先使用jps命令找到需要开启GC日志的Java进程ID:
# 查看所有Java进程 jps -l # 输出示例 12345 com.example.MainApplication 67890 sun.tools.jps.Jps
2. 动态修改GC日志参数
使用jinfo -flag命令修改目标进程的GC相关参数,开启GC日志输出到指定文件:
# 开启GC详细信息输出 jinfo -flag +PrintGCDetails 12345 # 开启GC时间戳输出 jinfo -flag +PrintGCDateStamps 12345 # 设置GC日志输出路径,注意路径需要提前存在 jinfo -flag GCLogFileSize=10M 12345 jinfo -flag NumberOfGCLogFiles=5 12345 jinfo -flag LogGC=/data/logs/gc/gc_%p.log 12345
上述命令执行后,JVM会立即开始将GC日志输出到/data/logs/gc/gc_12345.log文件中,如果日志文件大小达到10M会自动滚动,最多保留5个历史文件。
3. 验证GC日志是否生效
可以查看指定的GC日志文件,确认是否有日志输出:
tail -f /data/logs/gc/gc_12345.log
如果看到类似如下的GC记录,说明动态开启成功:
2024-05-20T10:30:00.123+0800: 1.234: [GC (Allocation Failure) [PSYoungGen: 1024K->512K(1536K)] 1024K->512K(2048K), 0.0012345 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
JDK 9+动态启用GC日志步骤
JDK 9及之后版本使用-Xlog参数统一管理日志,动态修改需要使用jcmd工具,操作方式如下:
1. 查找目标进程PID
同样先通过jps获取进程ID:
jps -l
2. 动态设置GC日志输出规则
使用jcmd的VM.log命令动态配置GC日志:
# 开启GC日志,输出到指定文件,包含gc、heap两个标签的日志,级别为info jcmd 12345 VM.log output=/data/logs/gc/gc_%p.log what=gc* heap* level=info # 如果需要日志滚动,可添加如下配置 jcmd 12345 VM.log output_options=filecount=5,filesize=10M
上述命令的含义是:将进程12345的GC相关、堆相关的info级别及以上日志输出到/data/logs/gc/gc_12345.log,日志文件最多5个,每个大小10M。
3. 验证配置生效
查看日志文件确认输出:
tail -f /data/logs/gc/gc_12345.log
JDK 9+的GC日志格式与JDK 8不同,示例内容如下:
[0.123s][info][gc] Using G1 [1.234s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 1024K->512K(2048K) 0.0012345s
注意事项
- 动态开启GC日志会增加一定的JVM开销,尤其是高频率GC的场景,建议在问题排查期间开启,排查完成后可以动态关闭。
- JDK 8关闭GC日志可以使用
jinfo -flag -PrintGCDetails 进程ID命令,JDK 9+可以使用jcmd 进程ID VM.log disable命令。 - 日志输出路径需要提前创建,并且JVM进程对该路径有写权限,否则会导致日志输出失败。
- 部分早期版本的JDK 8可能存在部分GC参数不支持动态修改的情况,建议先在小范围环境验证后再应用到生产环境。
总结
通过JVM提供的动态参数修改能力,我们可以在Java应用不重启的情况下开启GC日志,避免了重启带来的业务中断风险。不同JDK版本的操作方式略有差异,实际使用时需要根据运行环境的JDK版本选择对应的方案,快速获取GC运行数据,提升线上内存问题的排查效率。