Dump文件分析

本文介绍了Dump文件的概念及其在分析线程高占用、死锁等问题中的作用。详细解释了Dump文件的结构,包括如何生成和阅读Dump文件,以及如何从Dump文件中获取线程状态和锁信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要介绍Dump文件结构,理解Dump文件对于分析线程高占用、死锁、内存溢出等高级问题有非常重要的指导意义。

什么是Dump文件

Dump文件是进程的内存镜像。可以把程序的执行状态通过调试器保存到dump文件中。
Dump文件是用来给程序编写人员调试程序用的,这种文件必须用专用工具软件打开。

如何生成Dump文件

使用命令:jstack pid
可以查看到当前运行的java进程的dump信息。

Dump文件结构

首先浏览一下dump文件的文本内容:

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.77-b03 mixed mode):

"Attach Listener" #37 daemon prio=9 os_prio=0 tid=0x00007f87b42b7000 nid=0x680f waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Druid-ConnectionPool-Destory-331358539" #36 daemon prio=5 os_prio=0 tid=0x00007f87a4278800 nid=0x67e4 waiting on condition [0x00007f87b8dce000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.alibaba.druid.pool.DruidDataSource$DestroyConnectionThread.run(DruidDataSource.java:1724)

"Druid-ConnectionPool-Create-331358539" #35 daemon prio=5 os_prio=0 tid=0x00007f87a4022000 nid=0x67e3 waiting on condition [0x00007f87ce86a000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000b3804848> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:1629)

"Abandoned connection cleanup thread" #31 daemon prio=5 os_prio=0 tid=0x00007f87e0d91800 nid=0x672b in Object.wait() [0x00007f87cd2c2000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x00000000b422d1e8> (a java.lang.ref.ReferenceQueue$Lock)
        at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:43)

"DestroyJavaVM" #30 prio=5 os_prio=0 tid=0x00007f87e0008800 nid=0x670b waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"http-nio-8081-AsyncTimeout" #28 daemon prio=5 os_prio=0 tid=0x00007f87e016e800 nid=0x6727 waiting on condition [0x00007f87b94cf000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at org.apache.coyote.AbstractProtocol$AsyncTimeout.run(AbstractProtocol.java:1211)
        at java.lang.Thread.run(Thread.java:745)

"http-nio-8081-Acceptor-0" #27 daemon prio=5 os_prio=0 tid=0x00007f87e0166000 nid=0x6726 runnable [0x00007f87b95d0000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:422)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
        - locked <0x00000000b410d480> (a java.lang.Object)
        at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:455)
        at java.lang.Thread.run(Thread.java:745)

"http-nio-8081-ClientPoller-0" #26 daemon prio=5 os_prio=0 tid=0x00007f87e0292800 nid=0x6725 runnable [0x00007f87b96d1000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000b410d6c0> (a sun.nio.ch.Util$2)
        - locked <0x00000000b410d6b0> (a java.util.Collections$UnmodifiableSet)
        - locked <0x00000000b410d668> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:793)
        at java.lang.Thread.run(Thread.java:745)

"http-nio-8081-exec-10" #25 daemon prio=5 os_prio=0 tid=0x00007f87e028c000 nid=0x6724 waiting on condition [0x00007f87b97d2000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000b410d898> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:103)
        at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:31)
        at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

其中每个空行用于分隔一个线程,每个线程的信息是以堆栈信息的方式展开,显示了目前正在调用的方法以及所在的代码行。每个线程信息的第一行是描述该线程的基本信息,例如:

"http-nio-8081-exec-10" #25 daemon prio=5 os_prio=0 tid=0x00007f87e028c000 nid=0x6724 waiting on condition [0x00007f87b97d2000]

每一个部分的含义如下:

  • “http-nio-8081-exec-10” 线程名称
  • #25 线程编号
  • daemon 线程的类型
  • prio=5 线程的优先级别
  • os_prio=0 系统级别的线程优先级
  • tid=0x00007f87e028c000 线程ID
  • nid=0x6724 native线程的id
  • waiting on condition [0x00007f87b97d2000] 线程当前的状态

线程当前的状态是我们主要关注的内容。

dump文件中描述的线程状态

runnable:运行中状态,在虚拟机内部执行,可能已经获取到了锁,可以观察是否有locked字样。
blocked:被阻塞并等待锁的释放。
wating:处于等待状态,等待特定的操作被唤醒,一般停留在park(), wait(), sleep(),join() 等语句里。
time_wating:有时限的等待另一个线程的特定操作。
terminated:线程已经退出。

进程区域的划分

这里写图片描述
进入区(Entry Set):等待获取对象锁,一旦对象锁释放,立即参与竞争。
拥有区(The Owner):已经获取到锁。
等待区(Wait Set):表示线程通过wait方法释放了对象锁,并在等待区等待被唤醒。

方法调用修饰

locked: 成功获取锁
waiting to lock:还未获取到锁,在进入去等待;
waiting on:获取到锁之后,又释放锁,在等待区等待;
parking to wait for:等待许可证; (参考LockSupport.park和unpark操作)

结尾

有了这些知识之后我们再看前面的Dump文件就非常清楚了,清楚的描述了线程当前所处的状态以及获取到的锁的信息,例如:

"http-nio-8081-exec-2" #17 daemon prio=5 os_prio=0 tid=0x00007f87e0685800 nid=0x671c waiting on condition [0x00007f87cc5bd000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x00000000b410d898> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)

名称为‘http-nio-8081-exec-2’的线程当前正处于等待状态,等待其他线程释放许可证。(请先了解LockSupport的park和unpark操作)

"http-nio-8081-AsyncTimeout" #28 daemon prio=5 os_prio=0 tid=0x00007f87e016e800 nid=0x6727 waiting on condition [0x00007f87b94cf000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)

名称为‘http-nio-8081-AsyncTimeout’的线程当前处于等待状态,经过一个特定的休眠时间之后将自动唤醒。

综上所述,dump文件结构还是比较简单的,这对于我们分析线程的执行情况非常有用,是每一个Java程序员必须掌握的高级技能之一。

### 解析Dump文件以诊断Qt应用程序崩溃原因 解析Dump文件是定位Qt应用程序崩溃问题的重要手段之一。以下是针对该需求的具体方法和工具说明: #### 方法一:使用WinDbg进行Dump文件分析 WinDbg是一款功能强大的调试器,适用于Windows平台上的Dump文件分析。它可以加载符号文件(PDB),从而帮助开发者深入理解崩溃的根本原因。 1. **安装与配置** 确保已安装最新版本的WinDbg,并正确配置符号路径以解析堆栈信息[^5]。 2. **打开Dump文件** 在WinDbg中选择`File -> Open Crash Dump...`选项,加载目标`.dmp`文件。 3. **执行基本命令** 输入以下命令获取崩溃的相关信息: ```plaintext !analyze -v ``` 此命令会自动识别崩溃原因并显示详细的调用堆栈及其他上下文数据[^5]。 4. **查看源码关联** 若应用是以调试模式编译的,则可通过附加PDB符号进一步精确定位到具体的代码位置。 #### 方法二:借助Breakpad实现跨平台解决方案 如果需要兼容多操作系统环境,可以采用Google开发的Breakpad工具集。它提供了统一的方式处理崩溃报告。 1. **集成客户端库至应用** 将Breakpad SDK嵌入到Qt工程中,在检测到异常事件时自动生成minidump文件[^4]。 2. **提取符号表信息** 使用`dump_syms`工具从可执行二进制文件生成相应的`.sym`文件,便于后续匹配。 3. **解读核心现场** 调用`minidump_stackwalk`读取之前保存的DMP数据及其对应SYM表格,最终获得线程回溯详情与其他重要线索[^4]。 ```bash minidump_stackwalk <input_dmp_file> <symbol_directory> ``` #### 方法三:基于CrashPad的改进方案 CrashPad作为Breakpad的继任者,具有更高的性能表现和易用性特点。按照引用中的描述[^2],可以通过运行批处理脚本来快速完成一系列操作步骤: 1. 修改脚本参数适配实际项目结构; 2. 执行`crash.bat`启动整个流程; 3. 结果将以TXT文档形式呈现给用户查阅。 ```batch @echo off cd %~dp0 dump_syms.exe ./TestCrashPad.pdb > ./TestCrashPad.sym set crashName=TestCrashPad set /p content=<%crashName%.sym echo %content% for /f "tokens=4,5" %%i in ('echo %content%') do ( mkdir symbols\%%j\%%i move ".\\%crashName%.sym" "symbols\%%j\%%i" ) minidump_stackwalk.exe -s 9e1b2053-8a49-47be-b278-475bb2e1268e.dmp ./symbols >%crashName%.txt pause ``` 以上三种方式各有优劣,可根据实际情况灵活选用最适合自己团队的技术路线实施排查作业。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

shadon178

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

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

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

打赏作者

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

抵扣说明:

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

余额充值