惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Cloudflare Blog
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Tailwind CSS Blog
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
博客园 - 司徒正美
V
Visual Studio Blog
G
Google Developers Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
月光博客
月光博客
aimingoo的专栏
aimingoo的专栏
博客园_首页
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
S
SegmentFault 最新的问题
T
The Blog of Author Tim Ferriss
D
Docker
Vercel News
Vercel News
Recent Announcements
Recent Announcements
Last Week in AI
Last Week in AI
爱范儿
爱范儿
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏

博客园 - 人艰不拆_zmc

15000mAh 到底是什么概念?一篇看懂电池容量 go2_ros2_sdk 到底是干什么的?从 Go2、官方 SDK、ROS2 一路讲到 SLAM 和 Nav2 买了宇树 Go2 以后怎么二次开发?写给第一次做机器狗项目的人 买了一块 NVIDIA Jetson,怎么在上面安装 ROS2?从 JetPack 到 ROS2 的完整入门指南 NVIDIA Jetson 到底是什么?写给第一次接触机器人和边缘 AI 的人 ROS / ROS2 到底是什么?写给第一次接触机器人开发的人 大模型到底能同时多少人用?一篇看懂并发、排队与容量估算 大模型为什么有快有慢?一篇看懂响应速度背后的关键因素 技术小白也能看懂:大模型里的量化、蒸馏到底是什么意思? Codex 使用技巧:从“会聊天”到“真正能干活” 我终于搞懂了:Codex 对话中插件和 Skill 到底怎么用 我终于搞懂了 Agent Spec:它其实就是 Agent 的“标准设计图” 我终于搞懂了 Tool:原来不只是 Function Calling 里的函数 Skill 里的 Python 脚本,到底是不是 Tool? 我终于搞懂了 Codex 的 Plugin 和 Skill:顺便把 App、MCP 一次理清 我终于搞懂了 Codex 的“应用”:App 到底是什么,怎么添加和维护? 我终于搞懂了 Tool、Function Calling 和 MCP:大模型到底怎么知道该调哪个接口? 我终于搞懂了 MCP:从 HTTP API 到 ERP MCP Server 的完整入门 我终于搞懂了 Codex 的“记忆”是怎么回事 Codex 用久了越来越慢?我的上下文管理小技巧 我终于搞懂了 Codex 里的 Thread、Turn 和 Session 从 Qwen3.8-27B 到 FP8、NVFP4、MoE:一次搞懂几个常见大模型概念 FPS 是什么意思?简单理解 60 FPS、25 FPS 和视频帧率 DeepSeek Harness 明明像 AI Coding 工具,为什么又能用来构建各种 Agent? 使用 Codex 开发项目,怎么才能节约 Token? 模型里的 32K、128K、256K 是什么意思?简单聊聊上下文限制 Codex 一次对话到底会给模型发送什么?以 Spring Boot 项目为例讲清 Context、代码读取与 Token 消耗 AI Agent 中的 Rule 是什么?以 Codex 为例,小白也能看懂 我终于搞懂了 Harness:它不是论文,也不是标准,更不是 Codex 独有 小白也能看懂:RTSP 到底是什么?
Java Heap Dump详解
人艰不拆_zmc · 2025-09-17 · via 博客园 - 人艰不拆_zmc

1、什么是 Heap dump?

Java堆转储(Heap Dump)是Java虚拟机(JVM)在某一时刻内存使用情况的快照,它包含了该时刻所有对象的实例信息、类信息、字段值和引用关系等数据。堆转储文件通常以 .hprof或 .heap为扩展名,是诊断内存问题的关键工具。

当应用程序出现内存泄漏、内存溢出或性能下降时,堆转储可以提供 invaluable 的信息,帮助开发者定位问题根源。通过分析堆转储,你可以了解哪些对象占用了大量内存,哪些对象存在异常,以及对象之间的引用关系。

2、堆转储的核心内容

堆转储文件包含丰富的信息,主要包括:

信息类别

包含的具体内容

说明

​​堆信息​​

所有存活的对象实例、每个对象的类名、字段值(包括原生数据类型和引用)、对象的大小、对象之间的引用关系、垃圾回收器根对象(GC Roots)的信息

这是堆转储最核心的内容,用于分析内存使用情况

​​类信息​​

类加载器、类名、超类、静态字段信息

帮助理解应用程序中类的结构和分布

​​线程栈信息​​

生成快照时所有线程的调用堆栈(Stack Trace)和局部变量(Local Variables)信息

用于分析线程状态和执行路径

注意:堆转储并不直接包含元空间(Metaspace)的内存细节。元空间存储的类元数据(如类的字节码、方法代码、常量池中的部分信息)的管理方式与堆内存不同。但是,堆转储中会包含在堆中创建的 java.lang.Class对象,这些对象是类在堆中的表示。通过这些 Class对象,你可以了解到类的结构信息(如类名、类加载器、静态字段等),这在一定程度上间接反映了元空间中的内容。如果你需要分析元空间的内存溢出(OutOfMemoryError: Metaspace),通常需要结合其他工具(如 jstat -gc)来监控元空间的使用情况,并检查类加载器的活动。

3、生成堆转储的方法

有多种方法可以生成Java堆转储,下面介绍最常用的几种方式:

3.1 使用JVM参数自动触发

最简单且推荐的方式是配置JVM参数,在发生OutOfMemoryError时自动生成堆转储。

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof -jar your-app.jar 

参数说明​​:

  • -XX:+HeapDumpOnOutOfMemoryError:在发生OutOfMemoryError时自动生成堆转储;

  • -XX:HeapDumpPath:指定堆转储文件的保存路径。

优点:无需人工干预,自动在内存问题发生时捕获现场,非常适合生产环境使用。 

3.2 使用jmap工具

jmap是JDK自带的命令行工具,可以随时生成运行中Java进程的堆转储。

# 首先查找Java进程ID
jps -l

# 生成堆转储
jmap -dump:live,format=b,file=heapdump.hprof <PID>

参数说明​​:

  • live:只转储存活对象(会触发Full GC);
  • format=b:指定二进制格式;
  • file:指定输出文件路径。​​

优点:

  • 简单易用:只需一个命令即可生成Heap dump;
  • 无需修改应用代码:不需要在代码中添加任何额外的逻辑;
  • 实时生成:可以在应用运行时生成当前内存状态的快照。

缺点:

  • 对性能有影响:生成Heap dump过程中会暂停应用,尤其是大堆内存的应用,影响会更明显;
  • 需要权限:可能需要管理员权限来执行命令。

3.3 使用jcmd工具

jcmd也是JDK自带的命令行工具,可以执行多种JVM诊断命令,包括生成Heap dump。

命令示例:

jcmd <pid> GC.heap_dump heapdump.hprof

优点:

  • 功能强大:jcmd不仅能生成Heap dump,还能执行其他诊断命令。
  • 无需修改应用代码:如jmap一样,不需要在代码中添加任何额外的逻辑。

缺点:

  • 对性能有影响:生成Heap dump过程中会暂停应用。
  • 需要权限:可能需要管理员权限来执行命令。

3.4 使用jvisualvm

jvisualvm是一个图形化的监控和诊断工具,可以方便地生成Heap dump。

操作步骤:

  1. 启动jvisualvm工具。
  2. 选择需要生成Heap dump的Java进程。
  3. 在右键菜单或工具栏中选择“Heap Dump”。

优点:

  • 图形化界面:操作简单直观,适合不熟悉命令行的用户。
  • 实时生成:可以在应用运行时生成当前内存状态的快照。

缺点:

  • 对性能有影响:生成Heap dump过程中会暂停应用。
  • 需要权限:可能需要管理员权限来执行操作。
  • 依赖图形界面:在无图形界面的服务器环境中使用不便。

3.4 代码触发

可以通过在代码中调用HotSpotDiagnosticMXBean来生成Heap dump。

代码示例:

import com.sun.management.HotSpotDiagnosticMXBean;
import java.lang.management.ManagementFactory;

public class HeapDumpUtil {
    public static void dumpHeap(String filePath, boolean live) throws Exception {
        HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(
                ManagementFactory.getPlatformMBeanServer(),
                "com.sun.management:type=HotSpotDiagnostic",
                HotSpotDiagnosticMXBean.class);
        mxBean.dumpHeap(filePath, live);
    }

    public static void main(String[] args) throws Exception {
        dumpHeap("heapdump.hprof", true);
    }
}

优点:

  • 灵活性高:可以在特定条件下生成Heap dump,比如在捕获到异常时。
  • 自动化:可以集成到应用的监控和诊断逻辑中。

缺点:

  • 对性能有影响:生成Heap dump过程中会暂停应用。
  • 需要修改代码:需要在代码中添加生成Heap dump的逻辑。
  • 依赖特定JVM:HotSpotDiagnosticMXBean是HotSpot JVM特有的,不适用于其他JVM实现。

4、堆转储分析工具及方法

生成堆转储后,需要借助专业工具进行分析。以下是常用工具对比:

工具名称

类型

特点

适用场景

​​Eclipse MAT​​

独立工具

功能强大,提供泄漏嫌疑报告、支配树、直方图等

深度内存分析,定位内存泄漏

​​VisualVM​​

JDK自带

图形化界面,支持实时监控和堆转储分析

初步分析和实时监控

​​jhat​​

命令行工具

JDK自带,通过浏览器查看分析结果

快速简单分析

​​JProfiler​​

商业工具

全面性能分析功能,界面友好

专业性能调优

4.1 使用Eclipse MAT进行深度分析

Eclipse Memory Analyzer (MAT) 是功能最强大的堆转储分析工具,提供了多种分析视角:

  1. ​​泄漏嫌疑报告(Leak Suspects Report)​​:自动分析并给出潜在内存泄漏点;

  2. ​​直方图(Histogram)​​:查看每个类的实例数量和内存占用;

  3. ​​支配树(Dominator Tree)​​:显示保留内存最多的对象,是定位内存问题的关键;

  4. ​​对象查询语言(OQL)​​:允许执行自定义查询查找特定对象。

​​分析技巧​​:

  • 关注​​保留堆(Retained Heap)​​大小而非浅堆(Shallow Heap),保留堆表示回收该对象后能释放的内存总量;

  • 使用"Group By"功能按类加载器或包名分组查看对象;

  • 对比不同时间点的堆转储,观察对象增长趋势。

4.2 使用VisualVM进行分析

VisualVM提供了基本的堆转储分析功能:

  1. 打开VisualVM:jvisualvm;

  2. 选择"File" → "Load" → 导入堆转储文件;

  3. 在"Summary"、"Classes"和"Instances"选项卡中查看不同维度的信息。

VisualVM适合快速浏览堆转储内容,但对于复杂的内存问题,建议使用MAT进行深度分析。

5、注意事项与最佳实践

在使用堆转储时,需要注意以下几点:

  1. ​​性能影响​​:生成堆转储会触发STW(Stop-The-World),​​暂停所有应用线程​​,对线上服务可能有短暂影响,应在低峰期进行。

  2. ​​文件大小​​:堆转储文件可能非常大(通常与JVM堆大小相当),确保磁盘有足够空间。分析大文件也需要为分析工具(如MAT)分配足够内存(可修改其配置文件中的-Xmx参数)。

  3. ​​生产环境:推荐配置-XX:+HeapDumpOnOutOfMemoryError参数自动捕获OOM时的堆转储,避免在高并发期间手动生成堆转储,考虑使用-XX:+HeapDumpAfterFullGC和-XX:+HeapDumpBeforeFullGC参数结合GC事件生成堆转储。

  4. ​​分析技巧​​:比较不同时间点的堆转储,观察对象增长趋势,结合线程转储(Thread Dump)进行综合分析,注意保留堆(Retained Heap)比浅堆(Shallow Heap)更能反映真实内存影响。

  5. 安全考虑​​:堆转储可能包含内存中的敏感数据(如密码),需注意保密和安全处理

7 总结

Java堆转储是诊断内存问题的强大工具,掌握堆转储的生成和分析技巧对于解决内存泄漏、内存溢出等问题至关重要。通过本文的介绍,你应该了解了:

  1. 堆转储是JVM内存的快照,包含对象实例、引用关系等丰富信息;
  2. 有多种生成堆转储的方式,推荐使用-XX:+HeapDumpOnOutOfMemoryError自动捕获OOM时的现场;
  3. Eclipse MAT是功能最强大的分析工具,提供泄漏嫌疑报告、支配树等多种分析视角;
  4. 分析堆转储时关注保留堆大小而非浅堆大小,这更能反映真实内存影响;
  5. 在生产环境使用堆转储需注意性能影响和文件大小问题;

希望本文能帮助你在实际开发中更有效地使用堆转储工具,快速定位和解决内存问题。