JVM 内存分析实战:40MB 程序为什么占用了 180MB 内存?

发布时间:2026/6/9 10:27:09

JVM 内存分析实战:40MB 程序为什么占用了 180MB 内存? JVM 内存分析实战40MB 程序为什么占用了 180MB 内存一、背景华为云服务器配置 1.7GB 内存部署了一个 Spring Boot 单体应用blog-server-1.0.0.jar程序包大小约 40MB。应用使用 OpenJDK 1.8 运行目前没有业务访问量。通过top命令看到 Java 进程占用了约180MB 物理内存。40MB 的 jar 包为什么吃掉 180MB 内存这 180MB 里面到底有什么于是开始了一次从外到内的 JVM 内存分析。二、测试环境项目信息云服务商华为云 ECS操作系统Ubuntu 24.04.3 LTS总内存1.7 GiBJava 版本OpenJDK 1.8.0_482应用blog-server-1.0.0.jarSpring BootJVM 参数-Xms64M -Xmx256M -XX:NativeMemoryTrackingsummary三、分析过程第一步查看服务器整体内存free-htotal used free shared buff/cache available Mem: 1.7Gi 746Mi 155Mi 2.6Mi 1.0Gi 1.0Gi服务器整体可用内存约 1.0GB压力不大。第二步查看 Java 进程资源占用top-p1087963PID USER PR NI VIRT RES SHR S %CPU %MEM TIME COMMAND 1087963 root 20 0 2652448 190500 18688 S 1.3 10.5 0:09.85 javaRES 190500KB ≈ 186MB这就是要分析的 180MBVIRT 2.65GB虚拟内存大是正常的JVM 会预留地址空间第三步用 jstat 查看堆内存jstat-gc1087963S0C S1C S0U S1U EC EU OC OU MC MU YGC YGCT FGC FGCT 2176.0 2176.0 1638.3 0.0 17536.0 6188.5 43712.0 22471.7 54528.0 51169.3 48 0.206 2 0.055计算堆已用 S0U(1.6MB) EU(6.0MB) OU(21.9MB) ≈29.5MB元空间已用 MU ≈50.0MB堆 元空间 ≈80MB新问题186MB - 80MB 106MB这 106MB 去哪了第四步开启 NMT 查看完整内存分布在启动参数中加入-XX:NativeMemoryTrackingsummary重启后执行jcmd1087963VM.native_memory summary输出Total: reserved1662343KB, committed186727KB - Java Heap (committed65600KB) # 64.1 MB - Class (committed56621KB) # 55.3 MB元空间 - Thread (committed28798KB) # 28.1 MB - Code (committed17071KB) # 16.7 MB代码缓存 - Symbol (committed13911KB) # 13.6 MB符号表 - Native Memory Tracking (committed2356KB) # 2.3 MB - 其他GC/Internal等 # ~3.0 MB完整内存分布内存区域大小占比Java 堆64 MB34.4%元空间 (Class)55 MB29.7%线程栈28 MB15.1%代码缓存17 MB9.0%符号表14 MB7.3%其他~5 MB2.8%总计~186 MB100%第五步补充验证查看线程数jcmd1087963Thread.print|grep-c^\# 输出28确认 JVM 参数jcmd1087963VM.flags-XX:InitialHeapSize67108864 -XX:MaxHeapSize268435456 -XX:NativeMemoryTrackingsummary ...查看系统环境cat/etc/os-release# Ubuntu 24.04.3 LTSjava-version# openjdk version 1.8.0_482第六步生成 Heap Dumpjmap -dump:live,formatb,file/tmp/heap.hprof1087963ls-lh/tmp/heap.hprof# -rw-r--r-- 1 root root 40M heap.hprof生成 40MB 的 dump 文件可用 VisualVM 或 MAT 离线分析堆内对象构成。四、JDK 工具对比总结工具用途适用场景jstat查看堆内存、GC 统计日常监控jcmd多功能诊断NMT、线程、类统计功能最全面jmap生成 Heap Dump深入分析堆内对象jstack查看线程堆栈排查死锁、线程卡顿jconsole图形化监控可视化看内存/线程曲线jhat分析 Heap Dump已过时用 VisualVM/MAT 替代五、结论-Xmx只控制堆的最大容量元空间、线程栈、代码缓存、符号表等堆外内存不受它限制。Spring Boot 应用的元空间占用较高即使堆只有 64MB元空间也会因为加载近万个类而占用 50MB。186MB 对于小型 Spring Boot 应用是正常的内存占用不是内存泄漏。NMTNative Memory Tracking是分析堆外内存的有效工具建议在启动参数中开启。六、后续工具延伸如果遇到更复杂的内存问题堆外内存泄漏、高 CPU 问题定位JDK 自带工具可能不够用。阿里巴巴开源的Arthas提供了更强大的能力memory命令一键查看所有内存区域堆外内存追踪profiler命令生成火焰图进行方法级热点分析jad命令在线反编译运行时代码

相关新闻