← 返回首页

Heap Dump内存分析

📂 java ⏱ 2 min 260 words

Heap Dump内存分析

Heap Dump是Java堆内存的快照,用于分析内存泄漏、大对象和内存使用情况。

生成Heap Dump

# jmap命令
jmap -dump:live,format=b,file=heap.hprof <pid>

# OOM时自动生成
java -XX:+HeapDumpOnOutOfMemoryError \
     -XX:HeapDumpPath=/tmp/heap.hprof \
     -jar app.jar

# jcmd命令
jcmd <pid> GC.heap_dump /tmp/heap.hprof

# 代码中生成
HotSpotDiagnosticMXBean mxBean = ManagementFactory.getPlatformMXBean(
    HotSpotDiagnosticMXBean.class);
mxBean.dumpHeap("/tmp/heap.hprof", true);

使用Eclipse MAT分析

Leak Suspects Report

// MAT会自动检测可疑泄漏点
// 示例:大数组持有者
// Problem Suspect 1:
// 16,000 instances of "com.example.entity.User"
// loaded by "app classloader"
// occupy 128,000,000 (60%) bytes.

Dominator Tree

// 按对象保留内存排序
com.example.cache.UserCache @ 0x7ab5c2a80
  Retained Heap: 128MB
  Shallow Heap: 64B
    HashMap @ 0x7ab5c2b00
      Retained Heap: 128MB
        Object[64000] @ 0x7ab5c2c00

常见内存问题

内存泄漏示例

// 错误:静态集合持有对象引用
public class UserService {
    private static final List<User> users = new ArrayList<>(); // 持续增长

    public void addUser(User user) {
        users.add(user); // 永远不会被GC回收
    }
}

// 错误:未关闭的资源
public class FileService {
    public void readFile(String path) throws IOException {
        InputStream is = new FileInputStream(path);
        // 忘记关闭,导致资源泄露
    }
}

// 正确:使用try-with-resources
public class FileService {
    public void readFile(String path) throws IOException {
        try (InputStream is = new FileInputStream(path)) {
            byte[] data = is.readAllBytes();
        }
    }
}

大对象排查

# 使用jmap查看大对象
jmap -histo:live <pid> | head -20

# 输出示例:
# num   #instances   #bytes   class name
# 1:     500000    40000000   [B
# 2:     200000    16000000   java.lang.String

内存配置优化

# 堆内存设置
java -Xms4g -Xmx4g \
     -XX:NewRatio=2 \
     -XX:SurvivorRatio=8 \
     -jar app.jar

# 元空间设置
java -XX:MetaspaceSize=256m \
     -XX:MaxMetaspaceSize=512m \
     -jar app.jar

代码内存监控

@Component
public class MemoryMonitor {
    @Scheduled(fixedRate = 60000)
    public void checkMemory() {
        Runtime runtime = Runtime.getRuntime();
        long maxMemory = runtime.maxMemory();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;

        double usagePercent = (double) usedMemory / maxMemory * 100;
        if (usagePercent > 80) {
            log.warn("内存使用率过高: {}%", usagePercent);
        }
    }
}

小结

Heap Dump分析是排查内存问题的关键手段,结合MAT工具可快速定位内存泄漏和大对象问题。