如何编写查看分析垃圾回收运行状态

wen 实用脚本 30

本文目录导读:

如何编写查看分析垃圾回收运行状态

  1. JVM GC 查看方法
  2. GC 分析工具
  3. GC 状态指标解读
  4. 实战分析脚本
  5. 分析步骤
  6. 优化建议

我来详细介绍如何查看和分析垃圾回收(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运行状态,及时发现并解决内存和性能问题,建议在开发环境先行测试各种监控方案,选择最适合你应用的组合。

抱歉,评论功能暂时关闭!