Dump文件生成,内容,以及分析

本文介绍了在Java环境中如何排查服务器CPU和内存占用异常问题,主要涉及内存泄露的检测和分析。通过jstack、jmap等工具制作线程Dump和堆Dump,分析线程状态和内存占用,定位问题类。同时提到了分析工具如jhat和MAT的使用,以及关注的线程状态如waitonmonitorentry和inObject.wait()。此外,还分享了内存分析的关键点和常用工具有助于理解Java内存管理和优化。

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

​​​​​​​本文用到的工具只是简单介绍,让你有个感官认识,重点是核查思路的熟悉

为啥需要dump内存文件

服务器CPU,内存占用空间飙升,或者GC频繁,首先需要排除的就是内存泄露,即内存中没有的对象的空间没有被及时回收导致的。而检测内存泄露就需要看哪种类在内存占了较多份额,从而定位到代码,然后修改。


分析思路

1. cpu,mem 飙升,确认是否web服务的问题并记录pid

2. 查看GC情况,如果每次gc效果不明显说明内存泄露

3. 导出dump,分析。定位占用top n的类

4. 分析并找到 哪里创建的类占用了大量


制作dump

jstack

打印线程的栈信息,制作线程Dump。

jstack <进程ID> >> <输出文件>

jstack 2316 >> c:\thread.txt

## Linux下使用Kill命令制作线程Dump,输出线程Dump到目标Java进程的标准输出

kill -quit <进程ID>

kill -3 <进程ID>

jmap

使用jmap命令制作堆Dump

# 打印存活的对象大小和个数

jmap -histo:live <pid>

jmap -histo:live 64421 > live.log

# 二进制方式存储堆文件

jmap -dump:format=b,file=文件名.hprof <进程ID>

以二进制方式生成文件/opt/wkt/wkt1.hprof,进程PID=64421

jmap -dump:format=b,file=/opt/wkt/wkt1.hprof 64421


Dump读取前基础铺垫

Dump文件内容

制作时间

Java 版本

线程信息:名称、优先级、标识、状态、堆栈

死锁信息:存在直接Java线程的死锁时才包含。

内存信息:使用kill制作时才包含。

线程信息

线程状态

NEW: 未启动的。不会出现在Dump中。

RUNNABLE: 在虚拟机内执行的。

BLOCKED: 受阻塞并等待监视器锁。

WATING: 无限期等待另一个线程执行特定操作。

TIMED_WATING: 有时限的等待另一个线程的特定操作。

TERMINATED: 已退出的。

监视器(Monitor)

监视器:对象锁的访问控制结构。也指对象的锁。

监视器项:线程的代理人。

进入区:表示线程通过synchronized要求获取对象的锁。如果对象未被锁住,则进入拥有者;否则则在进入区等待。一旦对象锁被其他线程释放,立即参与竞争。

拥有者:表示某一线程成功竞争到对象锁。

等待区:表示线程通过对象的wait方法,释放对象的锁,并在等待区等待被唤醒。

调用修饰

locked <地址> 目标

waiting to lock <地址> 目标

waiting on <地址> 目标

parking to wait for <地址> 目标

实例锁: (a 类名)——synchronized对象。

类锁:(a Class for 类名)——静态synchronized方法

locked:通过synchronized关键字,成功获取到了对象的锁,成为监视器的拥有者,在临界区内操作。对象锁是可以线程重入的。

at oracle.jdbc.driver.PhysicalConnection.prepareStatement

- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)

at oracle.jdbc.driver.PhysicalConnection.prepareStatement

- locked <0x00002aab63bf7f58> (a oracle.jdbc.driver.T4CConnection)

at com..datasource.PooledConnection.prepareStatement

synchronized (conn) { // conn的类型是T4CConnection

// 同步块操作

}

waiting to lock:通过synchronized关键字,没有获取到了对象的锁,线程在监视器的进入区等待。在调用栈顶出现,线程状态为Blocked​​​​​​​​​​​​​​

at com..impl.CacheHolder.isVisibleIn(CacheHolder.java:165)

- waiting to lock <0x0000000097ba9aa8> (a CacheHolder)

at com..impl.CacheGroup$Index.findHolder

at com..impl.ContextImpl.find

at com..BaseDataCenter.findInfo

synchronized (holder) { // holder的类型是CacheHolder

// 临界区操作

}

waiting on:通过synchronized关键字,成功获取到了对象的锁后,调用了wait方法,进去对象的等待区等待。在调用栈顶出现,线程状态为WAITING或TIMED_WATING

at java.lang.Object.wait(Native Method)

- waiting on <0x00000000da2defb0> (a WorkingThread)

at com..WorkingManager.getWorkToDo

- locked <0x00000000da2defb0> (a WorkingThread)

at com..WorkingThread.run

synchronized(thread) {

     // 同步块操作……

     try {

           thread.wait();

     catch(InterruptException e) { /* 中断异常处理 */ }

}

parking to wait for

at sun.misc.Unsafe.park(Native Method)

- parking to wait for <0x00000000eb8f35c8> (a FutureTask$Sync)

at java.util.concurrent.locks.LockSupport.park(LockSupport:156)

...

at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock()

park是基本的线程阻塞原语,不通过监视器在对象上阻塞。

随concurrent包会出现的新的机制,与synchronized体系不同。

synchronized模型相关的调用修饰

1.locked <对象地址> (a 类名)

使用synchronized申请对象锁成功,监视器的拥有者。

2. waiting to lock <对象地址> (a 类名)

使用synchronized申请对象锁未成功,在进入区等待。

3. waiting on <对象地址> (a 类名)

使用synchronized申请对象锁成功后,释放锁并在等待区等待

分析模式

wait on monitor entry 被阻塞的,肯定有问题

runnable 注意IO线程

in Object.wait() 注意非线程池等待

虚拟机执行Full GC时,会阻塞所有的用户线程。因此,即时获取到同步锁的线程也有可能被阻塞。

"wss-635" waiting for monitor entry

  java.lang.Thread.State: BLOCKED (on object monitor)

    at com..impl.CacheHolder.isVisibleIn(CacheHolder.java:165)

    - locked <0x0000000097ba9aa8> (a com..CacheHolder)


分析工具

jhat

下载生成dump二进制文件wkt1.hprof,并下载到本地。

cmd中输入:jhat wkt1.hprof

 访问:http://localhost:7000/

jvisualvm

window可视化界面,Ctr+R,CMD,输入jvisualvm回车,打开主界面后,点击【文件】下【装入】

 查看类,可以看到不同类占的内存大小:

Jvm.分析工具(jps,jmap,jstack,jinfo,jconsole,jvisualvm,arthas,jprofiler,mat)_闲猫的博客-CSDN博客

MAT

MAT(MemoryAnalyzerTool)是Eclipse提供的一个内存分析工具,作为Java的内存分析中一个比较好用的工具,掌握MAT的基本用法基本上算是定位问题中一项最重要的基础技能了。

下载地址:链接:https://pan.baidu.com/s/1Qyy1bJQtosNlJ9VOt9GzVA 提取码:8hgd

Jvm.分析工具(jps,jmap,jstack,jinfo,jconsole,jvisualvm,arthas,jprofiler,mat)_闲猫的博客-CSDN博客

### 解析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
发出的红包

打赏作者

闲猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值