在 java 应用性能调优中,监控垃圾回收(gc)情况是关键环节。
以下是查看 java 进程 gc 状态的常用方法、工具及最佳实践:
一、命令行工具实时监控
1. jstat(jdk 自带)
功能:实时显示 jvm 内存和 gc 统计信息。
语法:
jstat -gc <pid> [间隔时间(ms)] [次数]
常用参数:
-gc
:显示 gc 相关统计。-gcutil
:显示 gc 利用率(百分比)。
示例:
jstat -gc 12345 1000 # 每 1000ms 输出一次 gc 统计
输出字段含义:
s0c:survivor0 区容量(kb) s1c:survivor1 区容量 s0u:survivor0 区已使用 ec:eden 区容量 eu:eden 区已使用 oc:老年代容量 ou:老年代已使用 mc:元空间容量 mu:元空间已使用 ygc:年轻代 gc 次数 ygct:年轻代 gc 总耗时(秒) fgc:full gc 次数 fgct:full gc 总耗时 gct:gc 总耗时
2. jstat 进阶用法
监控 gc 频率和内存增长趋势:
# 每 5 秒输出一次 gc 利用率,持续监控 jstat -gcutil 12345 5000
输出示例:
s0 s1 e o m ccs ygc ygct fgc fgct gct 0.00 99.81 93.21 42.35 92.83 89.75 126 0.536 1 0.024 0.560
关键指标:
e
(eden 区使用率)接近 100% 时触发 ygc。o
(老年代使用率)持续增长可能导致 fgc。ygc
和fgc
频率过高(如每分钟多次)需警惕性能问题。
二、gc 日志分析
1. 启用 gc 日志
在 jvm 启动参数中添加:
java -xx:+printgcdetails \ -xx:+printgcdatestamps \ -xx:+printheapatgc \ -xloggc:/path/to/gc.log \ -jar your-app.jar
参数说明:
printgcdetails
:打印 gc 详细信息。printgcdatestamps
:添加 gc 发生的时间戳。xloggc
:指定日志文件路径。
2. 手动触发 gc 并查看日志
jcmd <pid> gc.run # 手动触发 full gc tail -f /path/to/gc.log # 实时查看日志
3. 日志分析工具
gceasy:
上传 gc 日志到 gceasy,自动生成分析报告,包含:
- gc 频率和耗时分布。
- 堆内存使用趋势。
- 推荐的 jvm 参数优化建议。
gcviewer:
本地工具,可视化 gc 日志:
java -jar gcviewer-1.36.jar /path/to/gc.log
三、可视化工具监控 gc
1. visualvm(jdk 自带)
启动方式:
jvisualvm # jdk 8 及以前版本自带
监控步骤:
- 选择目标 java 进程 → 点击「monitor」选项卡。
- 查看「heap」和「perm gen」变化趋势。
- 点击「perform gc」手动触发 gc。
2. java mission control (jmc) + jfr
启动 jfr 记录:
jcmd <pid> jfr.start name=gcrecording settings=profile duration=5m filename=gc.jfr
分析 gc 事件:
- 使用 jmc 打开
.jfr
文件。 - 查看「garbage collections」视图,分析 gc 类型、耗时和内存变化。
四、生产环境低开销监控方案
1. prometheus + grafana
配置 jmx exporter:
java -javaagent:/path/to/jmx_prometheus_javaagent.jar=9090:/path/to/config.yaml -jar your-app.jar
grafana 仪表盘:
导入预定义的 jvm 监控仪表盘(如 id 14548
),查看:
- 堆内存各区域使用情况。
- gc 频率和耗时趋势。
- 类加载 / 卸载数量。
2. arthas(在线诊断工具)
查看 gc 统计:
dashboard # 实时查看 jvm 状态,包括 gc 信息
监控特定类的 gc 情况:
monitor -c 5 java.lang.string # 每 5 秒统计 string 对象的 gc 情况
五、gc 问题排查思路
1. 高频 full gc 排查
检查老年代增长趋势:
jstat -gcoldcapacity <pid> 1000 # 监控老年代容量变化
分析大对象分配:
使用 jfr 记录「object allocation in new tlab」事件,找出频繁创建大对象的代码。
2. 长时间 stw(stop the world)
检查 gc 类型:
通过 gc 日志确认是否为 cms 或 g1 的 full gc 导致。
优化建议:
- 增大堆内存(
-xmx
)。 - 调整垃圾收集器(如使用 g1 或 zgc)。
3. 内存泄漏预警
对比多次堆转储:
# 间隔 1 小时生成两次堆转储 jmap -dump:format=b,file=heap1.hprof <pid> sleep 3600 jmap -dump:format=b,file=heap2.hprof <pid>
使用 mat 对比两个堆转储,找出持续增长的对象类型。
六、gc 性能指标参考
指标 | 健康值参考 | 问题表现 |
---|---|---|
ygc 频率 | 几分钟到几十分钟一次 | 每秒多次 |
ygc 耗时 | 通常 < 100ms | 超过 500ms |
fgc 频率 | 几小时到几天一次 | 每小时多次 |
fgc 耗时 | 通常 < 500ms | 超过 1s |
老年代使用率 | 稳定在 30%-70% | 持续增长接近 100% |
gc 总耗时占比 | < 5% | 超过 10% |
七、jvm 参数优化建议
根据应用特点调整 gc 相关参数:
堆内存分配:
-xms2g -xmx2g # 堆内存初始值和最大值一致,避免动态调整
新生代比例:
-xx:newratio=2 # 老年代:新生代 = 2:1
垃圾收集器选择
# g1 适合大内存(> 8gb)应用 -xx:+useg1gc -xx:maxgcpausemillis=200 # zgc 适合极低延迟要求(< 10ms stw) -xx:+usezgc
通过以上方法,可全面监控 java 进程的 gc 状态,及时发现并解决内存泄漏、gc 频繁等性能问题。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论