记一次dump文件分析历程
一、背景
今天下午,正酣畅淋漓的搬砖,突然运维同事在群里通知,核心服务某个节点内存异常,服务假死。神经一下子紧张起来,赶紧跑到运维那边观察现象。
观察的结果是服务内存溢出,该服务是核心服务,分配了5G内存。运维在转存快照后,立刻重启服务后正常。在接下来的一段时间里,另一台服务节点也发生了同样的情况。
二、分析过程
这个服务是另外一个同事负责开发的,本着学习的态度,在拿到运维转存的dump文件后,就准备尝试着分析下问题,由于之前没有类似的经历,于是先在网上查了下一般怎么分析类似的问题。
首先尝试使用MAT(Memory Analyzer)工具进行分析,下载后就准备载入dump文件,很不幸由于dump文件过大,载入失败了,于是调大了内存大小,尝试再次载入,但此时这个文件不再尝试重新载入,直接提示载入失败。
先不纠结工具的问题,然后网上说JDK自带的jvisualvm也可以用来分析dump文件, 但也遇到了同样内存不足的问题,再尝试修改jvisualvm的内存限制后, 成功载入了。
看到的界面是这样的,很明显看到char[]占用了近70%的内存,接近4G,这太不正常了,点进去看对应的实例(加载的非常慢,需要耐心)。

在实例数界面中看到实例数达到了千万级,大部分都是一些文件的路径字符串信息。在业务中,我们会生成很多临时文件,然后这些临时文件会删除,这里面大部分保存的是这些临时文件路径。

到这里导致内存泄露的原因似乎找到了,但好像又还不够,是什么原因导致这些临时变量没有被回收呢。
回到家后,还是想着这个事情,于是又开始研究起来,这个时候想起来可以再用MAT试着分析下,毕竟据说工具很强大。重启了电脑之后,经过漫长的等待,载入成功了(果然重启能解决一切问题)。
MAT的界面是这样的,里面包含的信息比较多,对于我这个菜鸟来说,确实一下子不知道看哪里。
那就一个个慢慢看吧,Histogram里面的与使用jvisualvm中看到的信息是相同的。

接下来进入到Dominator Tree视图, 列出当前存活的对象的内存大小,这看起来像是我需要关注的重点。然后查了下这个类 java.io.DeleteOnExitHook 与 内存泄露的相关问题。

这个问题在下面两个链接中给出了说明,大概意思是在删除文件使用 File.deleteOnExit() 方法时,并不是立刻删除文件,而是将该文件路径维护在类DeleteOnExit的一个LinkedHashSet中,最后在JVM关闭的时候,才会去删除这里面的文件,这个方法不能用于长时间运行的服务。
https://stackoverflow.com/questions/40119188/memory-leak-on-deleteonexithook
https://bugs.openjdk.java.net/browse/JDK-6664633
上面的描述,通过源码和JDK文档也都得到了证明。
// java.io.File
// Requests that the file or directory denoted by this abstract pathname be deleted when the virtual machine terminates.
public void deleteOnExit() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkDelete(path);
}
if (isInvalid()) {
return;
}
DeleteOnExitHook.add(path);
}
// java.io.DeleteOnExitHook
private static LinkedHashSet<String> files = new LinkedHashSet<>();
static synchronized void add(String file) {
if(files == null) {
// DeleteOnExitHook is running. Too late to add a file
throw new IllegalStateException("Shutdown in progress");
}
files.add(file);
}
三、结论
问题定位于File.deleteOnExit()方法的调用,导致内存泄漏。调用该方法只会将需要删除文件的路径,维护在类DeleteOnExit的一个LinkedHashSet中,在JVM关闭时,才会去真正执行删除文件操作。这样导致DeleteOnExitHook这个对象越来越大,最终内存溢出。
File.delete()与 File.deleteOnExit() 的区别:
当调用delete()方法时,直接删除文件,不管该文件是否存在,一经调用立即执行
当调用deleteOnExit()方法时,只是相当于对deleteOnExit()作一个声明,当程序运行结束,JVM终止时才真正调用deleteOnExit()方法实现删除操作。
我写了下面这个测试方法,对比 delete()和deleteOnExit()的区别,现象会比较明显。使用deleteOnExit时是在文件全部创建,JVM关闭的时候,才一个个删除文件,delete会立刻删除文件。(所以这个方法的使用场景是怎样的,我就不太清楚了)
public static void loopTest() throws IOException {
String root = "D:\\C_Temp\\files\\";
File path = new File(root);
if (!path.exists()) {
path.mkdirs();
}
int i = 0;
while (i < 40000) {
File file = new File(path, "Hello-" + i + ".txt");
file.createNewFile();
file.delete();
// file.deleteOnExit();
i++;
}
}
四、收获
本次排查经历最大的收获就是尝试利用工具分析dump文件,以前对这种都是望而却步,感觉很难。但这次带着问题去分析、思考,这样下来也不算过于复杂。有些问题不是问题本身难,是自己把它想得很难。
下面是本次的一些思考和踩过的坑,以作备忘。
1. 获取dump文件有两种方法
1)通过 jmap 工具生成可以生成任意Java进程的dump文件
# 先找到PID
ps -ef | grep java
# jmap 转存快照
jmap -dump:format=b,file=/opt/dump/test.dump {PID}
2)通过配置JVM启动参数
# 当程序出现OutofMemory时,将会在相应的目录下生成一份dump文件,如果不指定选项HeapDumpPath则在当前目录下生成dump文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/dumps

2. MAT需要JDK11才能运行
解决办法是,打开MAT的安装目录,有一个配置文件MemoryAnalyzer.ini。打开这个文件,在文件中指定JDK版本即可。新增两行配置:
-vm D:/jdkPath/bin/javaw.exe
**3. 在使用jvisualvm分析大的dump文件时,堆查器使用的内存不足
修改JAVA_HOME/lib/visualvm/etc/visualvm.conf文件中 visualvm_default_options="-J-client -J-Xms24 -J-Xmx256m",然后重启jvisualVM即可
4. MAT修改内存空间
分析堆转储文件需要消耗很多的堆空间,为了保证分析的效率和性能,在有条件的情况下,建议分配给 MAT 尽可能多的内存资源。两种方式分配内存资源给 MAT:
1)修改启动参数 MemoryAnalyzer.exe -vmargs -Xmx4g
2)编辑文件 MemoryAnalyzer.ini 添加 -vmargs – Xmx4g
这里也列一个代办项
- 学习
MAT工具的使用
参考的一些文章:
- jvisualvm分析:https://zhuanlan.zhihu.com/p/163774290
- MAT定位大对象:https://www.cnblogs.com/rb2010/p/14741674.html
- MAT详细:https://blog.csdn.net/Jin_Kwok/article/details/80326088
- https://www.jianshu.com/p/82b25cf8cfde
记一次dump文件分析历程的更多相关文章
- 蓝屏 Dump文件分析方法
WinDbg使用有点麻烦,还要符号表什么的.试了下,感觉显示很乱,分析的也不够全面... 试试其他的吧!今天电脑蓝屏了,就使用其dump文件测试,如下: 1.首先,最详细的,要属Osr Online这 ...
- Windbg内核调试之四: Dump文件分析
Dump 文件分析很大程度上就是分析蓝屏产生的原因.这种系统级的错误算是Windows提示错误中比较严重的一种(更严重的还有启动黑屏等硬件或软件兼容性错误等等).说它是比较严重,是因为毕竟Window ...
- 使用GDB 追踪依赖poco的so程序,core dump文件分析.
前言 在windows 下 系统核心态程序蓝屏,会产生dump文件. 用户级程序在设置后,程序崩溃也会产生dump文件.以方便开发者用windbg进行分析. so,linux 系统也有一套这样的东东- ...
- core dump文件分析和调试
core介绍 当程序运行的过程中异常终止或崩溃,操作系统会将程序当时的内存状态记录下来,保存在一个文件中,这种行为就叫做Core Dump(中文有的翻译成"核心转储").我们可以认 ...
- Java Heap dump文件分析工具jhat简介
jhat 是Java堆分析工具(Java heap Analyzes Tool). 在JDK6u7之后成为标配. 使用该命令需要有一定的Java开发经验,官方不对此工具提供技术支持和客户服务. 用法: ...
- Windows Phone App的dump 文件分析
前言 我们在发布了自己的App以后,Windows Phone的Error Report机制会帮助我们收集程序的崩溃信息并发送到微软的服务器上,这可以辅助开发者提高App的稳定性. 那么如何利用这些d ...
- java OOM还在看log日志,兄弟你错的的很严重,正确方式是分析dump文件
目录 OOM异常--intsmaze 正确姿势dump文件分析--intsmaze 正确的姿势--intsmaze dump丢失打印--intsmaze 哪些内存溢出会产生dump文件--intsma ...
- JVM调优 dump文件怎么生成和分析
1.获取JVM的dump文件的两种方式 1. JVM启动时增加两个参数: #出现 OOME 时生成堆 dump: -XX:+HeapDumpOnOutOfMemoryError #生成堆文件地址: - ...
- 本地模拟内存溢出并分析Dump文件
java Dump文件分析 前言 dump文件是java虚拟机内存在某一时间点的快照文件,一般是.hprof文件,下面自己模拟一下本地内存溢出,生成dump文件,然后通过mat工具分析的过程. 配置虚 ...
随机推荐
- 如何在pyqt中实现窗口磨砂效果
磨砂效果的实现思路 这两周一直在思考怎么在pyqt上实现窗口磨砂效果,网上搜了一圈,全都是 C++ 的实现方法.正好今天查python的官方文档的时候看到了 ctypes 里面的 HWND,想想倒不如 ...
- 元数据性能大比拼:HDFS vs OSS vs JuiceFS
背景 存储是大数据的基石,存储系统的元数据又是它的核心大脑,元数据的性能对整个大数据平台的性能和扩展能力非常关键.本文选取了大数据平台中 3 个典型的存储方案来压测元数据的性能,来个大比拼. 其中 H ...
- 不使用pvc的方式在K8S中部署apisix-gateway
不使用pvc的方式在K8S中部署apisix-gateway 简介 我的apisix使用etcd作为数据存储服务器,官方的使用pvc方式或者docker-compose的方式,对于新手不太友好,本篇是 ...
- 对线面试官,凭借nginx能一战封神吗?
面试官:小伙子,你对nginx熟悉吗? 我:当然熟悉了,请听我慢慢道来. 心里想,我能吊打面试官吗?今天非得灭一灭面试官的威风,平时都被怼的狗血淋头. 面试官:就你那点花花肠子,咱还不清楚. 我:.. ...
- MySQL 新增表分区很慢,转移大表数据
问题: MySQL (version 5.7.26) 数据库有一批表 xxx_yyy,由于评估的数据量可能比较大,因此每张表都设置了表分区,把每个月的数据保存在单独的分区里. 那么如果每年年末,没有提 ...
- nginx的优化和防盗链
nginx的优化和防盗链 目录 nginx的优化和防盗链 一.nginx的优化 1. 隐藏版本号 (1)隐藏版本号的原因 (2)查看版本号的方法 (3)隐藏方法一:修改配置文件 (4)隐藏方法二:修改 ...
- 再见收费的Navicat!操作所有数据库就靠它了!
作为一名开发者,免不了要和数据库打交道,于是我们就需要一款顺手的数据库管理工具.很长一段时间里,Navicat 都是我的首选,但最近更换了一台新电脑,之前的绿色安装包找不到了. 于是就琢磨着,找一款免 ...
- Solution -「多校联训」古老的序列问题
\(\mathcal{Description}\) Link. 给定序列 \(\{a_n\}\),和 \(q\) 次形如 \([L,R]\) 的询问,每次回答 \[\sum_{[l,r]\su ...
- suse 12 二进制部署 Kubernetets 1.19.7 - 第08章 - 部署kube-scheduler组件
文章目录 1.8.部署kube-scheduler 1.8.0.创建kube-scheduler请求证书 1.8.1.生成kube-scheduler证书和私钥 1.8.2.创建kube-schedu ...
- InfluxDB 2.x Open Source Time Series Database
1. 说明 目前,大家普遍还在采用 InfluxDB 1.x 的版本,官方2.x的版本已经发布一段时间了, 其主推flux语言且自带前端炫酷图表. 2. 官方网站 https://www.influx ...