JVM 调优之 Dump 文件详解(Heap Dump + Thread Dump)

JVM Dump 是故障定位、性能调优、内存泄漏、死锁分析的核心依据,主要分两大类:线程快照 (Thread Dump)堆快照 (Heap Dump),下面从概念、场景、生成、分析、实战逐一讲解。


一、基础概念区分

1. Thread Dump(线程转储 / 线程快照)

  • 定义:某一时刻 JVM 内所有线程的运行状态、调用栈、锁信息的文本快照。
  • 作用:排查死锁、线程阻塞、线程池耗尽、CPU 飙高、接口卡顿、死循环
  • 格式:纯文本,体积小、生成快,可多次连续抓取。

2. Heap Dump(堆转储 / 堆快照)

  • 定义:某一时刻 JVM 整个堆内存(新生代、老年代、元空间除外) 的对象实例、引用关系、对象大小、类信息的二进制文件。
  • 作用:排查内存泄漏、OOM、堆内存溢出、大对象、内存占用过高
  • 格式:二进制 .hprof 文件,体积和堆内存一致,大堆生成 / 分析较慢。

补充:还有 GC Dump(GC 日志)、JFR 飞行日志,不属于传统 Dump,是辅助调优手段。


二、Thread Dump 线程快照(重点:线程问题排查)

1. 线程状态(核心识别点)

JVM 线程常见 6 种状态,Dump 中关键字对应:

  1. RUNNABLE:可运行 / 正在执行(CPU 繁忙、死循环多为此状态)
  2. BLOCKED被锁阻塞(等待 synchronized 锁,典型死锁场景)
  3. WAITING:无限等待(wait()/join(),主动休眠等待唤醒)
  4. TIMED_WAITING:限时等待(sleep()wait(time)、线程池空闲线程)
  5. TERMINATED:线程已结束
  6. NEW:线程未启动

2. 生成 Thread Dump 的 4 种常用方式

前提:先拿到 Java 进程 PID

# 查Java进程PID
jps -l
# 或
ps -ef | grep java

方式 1:jstack(最常用,JDK 自带)

# 单次输出到控制台
jstack 进程PID

# 输出到文件(推荐)
jstack PID > thread_dump_$(date +%Y%m%d%H%M).log

# 连续抓取3次(间隔2秒,排查瞬时卡顿/死循环)
jstack PID > td1.log
sleep 2
jstack PID > td2.log
sleep 2
jstack PID > td3.log

方式 2:kill -3(Linux 原生,不杀进程)

kill -3 PID
  • 不会终止进程,线程栈直接输出到 JVM 标准错误流(Tomcat/Java 容器一般输出到 catalina.out、nohup.out)。

方式 3:Arthas(线上首选,无侵入)

线上生产环境优先用 Arthas,无需重启:

# 进入arthas
as
# 查看所有线程栈
thread
# 查看指定线程栈
thread 线程ID
# 一键导出全量线程dump
thread -all > /tmp/thread.log

方式 4:JVisualVM / JConsole(图形化,本地测试)

可视化工具直接点击「线程→线程 Dump」,适合开发环境。

3. 典型问题 & 解读案例

(1)死锁 Deadlock

Dump 末尾会明确提示 Found 1 deadlock.,同时标注两个线程互相持有对方锁。 现象:接口卡死、服务不响应、线程大量 BLOCKED。

(2)CPU 100%(线程死循环)

排查步骤:

  1. top -Hp PID 找到占用 CPU 最高的线程 TID(十进制)
  2. 转十六进制:printf "%x\n" 十进制TID
  3. jstack PID 搜索十六进制线程 ID,定位死循环代码行。

(3)线程池耗尽、任务堆积

大量线程处于 WAITING,栈帧卡在线程池 getTask(),说明任务提交速度 > 处理速度。


三、Heap Dump 堆快照(重点:内存泄漏、OOM)

1. 触发时机 & 应用场景

适用场景:

  • 应用抛出 java.lang.OutOfMemoryError: Java heap space 堆溢出
  • 内存持续上涨、Full GC 频繁、GC 后内存不释放(内存泄漏
  • 排查大对象、大集合、静态集合常驻内存

2. 生成 Heap Dump 的 5 种方式

方式 1:OOM 自动生成(生产必配JVM 参数)

发生 OOM 时自动 dump 堆,事后溯源最有效,无需人工干预。

# JDK8 常用配置
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/data/jvm/dump/heap_dump.hprof

参数说明:

  • +HeapDumpOnOutOfMemoryError:OOM 时自动生成堆快照
  • HeapDumpPath:指定 dump 文件路径(建议独立磁盘,避免占满分区)

注意:堆多大,文件就多大,大堆 (8G/16G) 生成会卡顿,短暂影响业务

方式 2:jmap(JDK 自带命令,手动抓取)

# 1. 导出整个堆(包含所有对象,完整分析,推荐)
jmap -dump:format=b,file=/tmp/heap.hprof PID

# 2. 只导出存活对象(忽略已死对象,文件更小)
jmap -dump:live,format=b,file=/tmp/heap_live.hprof PID

# 3. 查看堆概览(先看整体,不用分析大文件)
jmap -heap PID

风险提醒

  • jmap 会触发 STW(Stop-The-World),堆越大、停顿越久。
  • 生产大堆(>4G)不建议频繁执行,优先用 Arthas / JFR。

方式 3:Arthas(线上低侵入抓取,推荐生产)

# 进入arthas后,导出堆快照
heapdump --live /tmp/heap.hprof
  • --live:只导出存活对象,体积更小、速度更快。

方式 4:JVisualVM / JConsole 图形化

本地测试、测试环境使用,界面点击「堆 Dump」即可。

方式 5:JVM 启动参数 -XX:+DumpHeapBeforeFullGC

每次 Full GC 前自动 dump,用于排查频繁 Full GC。

3. 关键 JVM 参数补充(Dump 相关)

# 限制dump文件大小、压缩等(可选)
-XX:+HeapDumpCompressionLevel=1  # 压缩hprof,减小体积
-XX:HeapDumpTimeout=300          # dump超时时间

4. Heap Dump 核心分析工具

(1)MAT(Eclipse Memory Analyzer,行业标准

  • 开源、功能最强,专门分析 .hprof
  • 核心功能:泄漏可疑报告、对象直方图、支配树、线程栈、引用链
  • 用法:打开 hprof 文件 → 选择 Leak Suspects(泄漏疑点) 一键分析。

(2)JVisualVM

JDK 自带,轻量,适合简单分析、本地调试。

(3)JProfiler

商业工具,可视化强,付费,企业常用。

(4)在线工具(小文件临时分析)

如 HeapHero,适合几 G 以内小堆快速查看。

5. 堆 Dump 核心分析思路(调优实战流程)

  1. 看直方图(Histogram) 按类统计对象数量、占用内存,找出实例数异常多、单类占比极高的类。

  2. 查大对象 / 大集合 定位 ArrayList/HashMap 等集合无限膨胀、未释放。

  3. 分析引用链(Reference Chain) 找到「谁持有这个对象的引用」—— 内存泄漏本质:对象本该被 GC,却被强引用一直持有。 常见泄漏点:

    • 静态集合(static List)不断 add 不 clear
    • 线程池、ThreadLocal 未手动 remove
    • 数据库连接、IO 流、缓存未关闭 / 过期
    • 第三方框架内存泄漏
  4. 查看类加载 & 元空间 区分是堆溢出还是元空间溢出(Metaspace OOM)


四、Thread Dump vs Heap Dump 选型(什么时候用哪个?)

现象优先使用典型问题
CPU 持续 100%、接口超时、卡死Thread Dump死循环、死锁、线程阻塞
OOM 报错、内存持续上涨、Full GC 频繁Heap Dump内存泄漏、大对象、堆溢出
服务间歇性卡顿、偶发超时两者结合线程阻塞 + 内存波动

五、线上生产最佳实践(避坑)

  1. 必配 OOM 自动 Dump 参数 线上所有 Java 应用强制加上 HeapDumpOnOutOfMemoryError,出问题才有溯源依据。
  2. Dump 文件单独挂载磁盘 避免堆很大时,dump 文件占满系统盘导致服务宕机。
  3. 大堆慎用 jmap -dump 8G+ 堆优先用 Arthas 抓取,减少 STW 停顿。
  4. 抓取策略
    • 线程问题:连续抓 2~3 份 Thread Dump(间隔 2s)对比状态。
    • 内存问题:GC 高峰期抓取 Heap Dump,优先加 --live
  5. Dump 文件及时清理 hprof 文件体积巨大,分析完立即删除。

六、常见问题答疑

  1. Dump 文件打不开 / 分析卡顿?
    • 增大 MAT/JVisualVM 的启动堆内存(修改 mat.ini 加大 -Xmx)。
  2. 多次 Dump 内容不一样正常吗? 正常,线程、对象状态是动态变化的。
  3. live 和不 live 区别? live 只保留存活对象,文件小、分析快;不带 live 包含垃圾对象,适合完整复盘。
  4. STW 影响业务怎么办? 低峰期抓取,或使用 JFR(Java Flight Recorder)替代,几乎无停顿。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超梦dasgg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值