java获取到heapdump文件后,如何快速分析?

标签: java heapdump 文件 | 发表时间:2023-04-21 22:08 | 作者:扣钉日记
出处:https://juejin.cn/backend

原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明。

简介

在之前的OOM问题复盘之后,本周,又一Java服务出现了内存问题,这次问题不严重,只会触发堆内存占用高报警,没有触发OOM,但好在之前的复盘中总结了dump脚本,会在堆占用高时自动执行jstack与jmap,使得我们成功保留了问题现场。

查看堆占用分布

发现有heapdump文件后,我立马拷贝到本机,并使用MAT分析,如下:
mat
很显然,好像是什么接口分配了非常大的String对象,一个String对象约200MB,那它是哪分配的呢?

查找大对象分配线程

这个分配行为肯定是某个线程做的,而线程是最常见的GC Root,因此只要查找对象的GC Root即可,如下:
gc_root
找到了大对象对应的分配线程是http-nio-8088-exec-6,如下:
image_2023-04-21_20230421200748

查看线程栈

如何查看这个线程在干什么呢?在MAT中摸索了一会,没找到相关内容,回想起我们的dump脚本中记录了jstack,打开看看,如下:
jstack
可以发现,这个线程正在做json序列化,但我仔细找了好一会,也没有找到相关接口的Controller,这是因为线程已经执行完了Controller里面的逻辑,之后返回接口响应数据时分配的大对象。

可是,线程栈中没有业务代码,就没法定位是哪个接口有问题了。。。

检查accesslog日志

考虑到分配大对象的接口肯定会很慢,于是我转向查看tomcat的accesslog日志,如下:
accesslog
终于,找到了问题接口,这个接口是用来查询商品数据的,当输入3时会查询出所有3开头的商品,而这有20w+数据,解决问题很简单,加个limit完事。

排查过程复盘

然而,我一直有个习惯,就是解决一个问题后,我会反思一下问题解决过程中有多少运气成分。

如果你经常阅读排查问题类的技术文章,就会发现不少文章,中间突然有一步定位到了问题根因,可能是突然发现了一个线索,或是硬看代码看出来的,或是猜测某处有问题,我觉得这种排查过程都有不少运气成分,我希望问题是通过多年理论基础的积累和对诊断工具的熟练使用,而有章法的一步步查出来的。

而上面通过accesslog能够定位到问题,有一定的运气成分,因为本次内存问题不极端,如果此接口请求量大,那就会瞬间触发多次FGC,进而会影响其它接口也变慢,进而无法分辨出哪个是导致问题的接口!

我想,从理论上来说,Java堆文件里面,应该有线程栈以及线程栈上的参数,因为线程是对象,参数也是对象,它们理应都在堆里,于是我找了个空闲时间,又摸索起MAT这个工具了。

MAT查看线程栈

摸索了一会,我就发现有这样一个按钮,可以查看线程信息,如下:
mat_thread

找到前面说的线程http-nio-8088-exec-6,展开后,就可以发现线程栈以及栈上的参数,如下:
mat_thread_stack

这就找到了请求的Request参数对象,再将Request对象多次展开后,就可以找到接口url信息,如下:
mat_request
嗯,这样分析heapdump文件真tm的高效啊

MAT下载地址:https://www.eclipse.org/mat/downloads.php

VisualVM查看线程栈

考虑到不少同学习惯用VisualVM分析heapdump,这里也放一下VisualVM的使用方法。

首先,加载heapdump文件,如下:
VisualVM_open

然后选择相应对象,右键选择Select in Threads,如下:
image_2023-04-21_20230421211033

定位到线程栈后,找到要查看的Request对象,点击进入,如下: image_2023-04-21_20230421211738

同样,展开Request对象后,可找到url信息,如下:
image_2023-04-21_20230421211858

VisualVM下载地址:https://visualvm.github.io/download.html

总结

虽然我也用MAT很多次了,但每次问题都太简单,以至于没有深入使用过MAT,导致到现在才知道有如此便捷的分析路径。

如果你对我们的自动dump脚本感兴趣,可看看我之前写的这两篇文章。
一次线上OOM问题的个人复盘
jmap执行失败了,怎么获取heapdump?

相关 [java heapdump 文件] 推荐:

Java中的JavaCore/HeapDump文件及其分析方法

- - 开源软件 - ITeye博客
Java程序运行时,有时会产生JavaCore及HeapDump文件,它一般发生于Java程序遇到致命问题的情况下. 有时致命问题发生后,Java应用不会死掉,还能继续运行;. 但有时致命问题发生,Java进程会死掉;. 为了能够保留Java应用发生致命错误前的运行状态,JVM在死掉前产生两个文件,分别为JavaCore及HeapDump文件.

java获取到heapdump文件后,如何快速分析?

- - 掘金 后端
原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明. 在之前的OOM问题复盘之后,本周,又一Java服务出现了内存问题,这次问题不严重,只会触发堆内存占用高报警,没有触发OOM,但好在之前的复盘中总结了dump脚本,会在堆占用高时自动执行jstack与jmap,使得我们成功保留了问题现场.

Java的 class文件结构

- - Java - 编程语言 - ITeye博客
Java-class文件结构.        我们都知道我们现在写的源代码计算机是不认识的,我们需要根据指定的编译器进行编译-连接-执行,这样才是我们想要的结果,所以计算机只能认识0或者1 ,那么如何与操作系统或者机器指令无关的程序能执行,那么在操作系统以及机器指令之上的那就是虚拟机了,这样我们编写的代码不再是最终形成二进制本地指令代码,而是一种在操作系统和机器指令之上的虚拟机规定的文件格式.

Java写xml文件的编码问题

- - CSDN博客推荐文章
最近项目中需要生成xml格式的配置文件,用的是 javax.xml.transform.Transformer 类中提供的transform方法,在本地执行没问题,但是一旦把工程部署到Tomcat下运行,就会出现中文乱码的现象,纠结了许久,在大神的帮助下终于解决了. 有篇文章其实已经讲的很清楚了,链接如下:.

JAVA 动态(手动)加载jar文件

- - CSDN博客编程语言推荐文章
//filePath 是jar的绝对路径. //里面是一个url的数组,可以同时加载多个. //根据类名加载指定类,例:. //通过反射调用类中的方法,例如调用addFile方法,有1个String参数和一个int参数:. 如果有返回值,则直接返回需要的值,例:. 作者:kingboy123000 发表于2013-10-23 16:12:30 原文链接.

使用Java处理大文件

- - ImportNew
我最近要处理一套存储历史实时数据的大文件 fx market data,我很快便意识到,使用传统的InputStream不能够将它们读取到内存,因为每一个文件都超过了4G. 甚至编辑器都不能够打开这些文件. 在这种特殊情况下,我可以写一个简单的bash脚本将这些文件分成更小的文件块,然后再读取它.

Java读取远程主机文件

- - ITeye博客
//Java利用第三方jar包(ganymed-ssh2-build210.jar)读取远程主机文件. String idxMasterPath = useHome+"ADR/cb/data/master/";   //主侧IDX文件路径. String idxSlavePath = useHome+"ADR/cb/data/slave/";     //备侧文件路径.

分析一个Java Class文件

- - CSDN博客推荐文章
Java源码文件TestClass.java:. 展示这个Class文件的16进制内容:. 00 00 00 34 : 版本号是1.8.0;. 00 16: 说明常量池有21个常量,1-21, index留做他用;接下来就是分别这21个常量的描述:. 07/00 02 :CONSTANT_Class_info 常量,类名索引是该常量池的第2项;.

Java根据文件头获取文件类型

- - BlogJava_首页
文件头是位于文件开头的一段承担一定任务的数据,一般都在开头的部分. 头文件作为一种包含功能函数、数据接口声明的载体文件,用于保存程序的声明(declaration),而定义文件用于保存程序的实现 (implementation).      为了解决在用户上传文件的时候在服务器端判断文件类型的问题,故用获取文件头的方式,直接读取文件的前几个字节,来判断上传文件是否符合格式.

java,根据头文件判断文件类型

- - Java - 编程语言 - ITeye博客
web判断文件的格式的时候,我们一般都是通过扩展名来判断,这个有点不太靠谱和安全. 下面是利用头文件来判断的代码:. * 根据文件流读取图片文件真实类型.  网上搜索了一些头文件的格式,但是强调一下,txt文件没有固定的头名,需要另外考虑,供参考:. JPEG (jpg),文件头:FFD8FF  .