本文目录导读:

我来详细介绍如何查看和分析垃圾回收(GC)运行状态的方法。
JVM GC 查看方法
命令行工具
jstat(推荐)
# 查看GC概览 jstat -gc <pid> <间隔ms> <次数> jstat -gc 12345 1000 5 # 查看GC详细信息 jstat -gcutil <pid> 1000 jstat -gccause <pid> 1000
jcmd(Java 8+)
# 查看GC相关信息 jcmd <pid> GC.heap_info jcmd <pid> GC.run jcmd <pid> VM.native_memory
GC日志
启用GC日志
# Java 8 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/path/to/gc.log # Java 9+ -Xlog:gc*:file=/path/to/gc.log:time,uptime,level,tags
JMX监控
// 程序内监控代码
import java.lang.management.*;
public class GCMonitor {
public static void monitorGC() {
List<GarbageCollectorMXBean> gcBeans =
ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean gcBean : gcBeans) {
System.out.println("GC名称: " + gcBean.getName());
System.out.println("GC次数: " + gcBean.getCollectionCount());
System.out.println("GC耗时: " + gcBean.getCollectionTime() + "ms");
}
}
}
GC 分析工具
GCeasy(推荐)
- 在线分析工具
- 自动生成分析报告
- 给出优化建议
GCEasy 分析脚本
# 解析GC日志 gceasy -f gc.log -o report.html
GCViewer
# 可视化分析 java -jar gcviewer.jar gc.log
GC 状态指标解读
关键指标
Young GC: - 频率: 每次间隔时间 - 耗时: STW暂停时间 - 晋升率: 对象晋升老年代速率 Full GC: - 频率: 发生次数 - 耗时: 暂停时间 - 原因: System.gc() / 空间分配担保失败 Heap: - 使用率: 各代内存使用 - 吞吐量: 应用线程时间 / (应用线程+GC时间) - 暂停时间: STW持续时间
分析示例
// 阈值判断工具类
public class GCHealthCheck {
// 健康指标
private static final int MAX_YOUNG_GC_PAUSE = 50; // ms
private static final int MAX_FULL_GC_PAUSE = 200; // ms
private static final double MAX_GC_OVERHEAD = 0.1; // 10%
public static boolean isGCHealthy(long gcTime, long totalTime) {
double gcOverhead = (double) gcTime / totalTime;
return gcOverhead < MAX_GC_OVERHEAD;
}
}
实战分析脚本
Shell 监控脚本
#!/bin/bash
# gc_monitor.sh
PID=$1
INTERVAL=5
while true; do
echo "=== $(date) ==="
# GC统计
jstat -gcutil $PID
# 堆内存使用
jmap -heap $PID | grep -E "used|capacity"
# 线程信息
jstack $PID | grep -c "WAITING|BLOCKED"
sleep $INTERVAL
done
Java 监控程序
public class GCRealTimeMonitor {
private static final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public static void startMonitoring() {
scheduler.scheduleAtFixedRate(() -> {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
// 堆内存
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
double heapUsedPercent = (double) heapUsage.getUsed() /
heapUsage.getMax() * 100;
// GC信息
for (GarbageCollectorMXBean gc :
ManagementFactory.getGarbageCollectorMXBeans()) {
long count = gc.getCollectionCount();
long time = gc.getCollectionTime();
if (count > 0) {
double avgPause = (double) time / count;
System.out.printf("GC: %s, 次数: %d, 平均暂停: %.2fms%n",
gc.getName(), count, avgPause);
}
}
// 告警
if (heapUsedPercent > 90) {
System.err.println("警告:堆使用率超过90%");
}
}, 0, 5, TimeUnit.SECONDS);
}
}
分析步骤
快速诊断
# 1. 查看进程 jps -l # 2. 基本GC状态 jstat -gc <pid> 1000 5 # 3. 堆转储(必要时) jmap -dump:live,format=b,file=heap.hprof <pid>
问题定位
// 内存泄漏检测
public class MemoryLeakDetector {
public static void detectLeak() {
Runtime runtime = Runtime.getRuntime();
// 记录基准内存
long baseMemory = runtime.totalMemory() - runtime.freeMemory();
// 执行操作后检查
long currentMemory = runtime.totalMemory() - runtime.freeMemory();
long diff = currentMemory - baseMemory;
if (diff > 100 * 1024 * 1024) { // 100MB增长
System.err.println("可能的内存泄漏,内存增长: " + diff);
}
}
}
优化建议
GC参数调整
# G1GC 优化示例 -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=16m -XX:InitiatingHeapOccupancyPercent=45 -XX:ConcGCThreads=4
告警阈值
Critical Alerts: - Full GC > 1次/小时 - GC暂停 > 1秒 - 堆使用率 > 90% - GC开销 > 10% Warning: - Young GC > 10次/分钟 - GC暂停 > 200ms - 堆使用率 > 80%
通过这些方法和工具,你可以全面监控和分析GC运行状态,及时发现并解决内存和性能问题,建议在开发环境先行测试各种监控方案,选择最适合你应用的组合。