让我们在一个舒缓的 BGM 中开始今日话题 内存溢出
很多伙伴,在碰到内存溢出,根本无从先下手,甚至重启已经成为解决问题的常态,面试追问场景,也只是熟练背诵八股文而已,那么这篇文章,带你详细从问题的发生到排查做一个讲解。
忽略如何发现的 OOM,以及与运维等角色协同,直接进入问题解决,来日方长,慢慢介绍。
某天小李手机突然疯狂开始震动,监控系统告警,某服务疯狂 OOM,如果不快速处理,可能也会拖累到服务器本身, 小李心想,这些问题,我也一知半解的,那谁谁,小白手套,这次就你来吧,不懂可以问我。
小白手套OS:真倒霉,行吧 ,我来看。
小白手套不情愿的登录到了公司服务器,查看日志,果然,OOM 错误
吞没了屏幕
小白手套很快注意到了 Java heap space
,按照常理来讲,一般是堆内存被分配光了,可是生产环境,一般分配都是经过严谨评估的,嗯,对了,记得生产有配置如果发生 OOM 自动 Dump 堆内存的,我去找找这个文件,问题就会水落石出。
很快,小白手套找到了堆转储文件
MAT(Memory Analyzer Tool)是一个用于分析Java堆内存使用情况和排查内存泄漏问题的强大工具。它是一个开源项目,由Eclipse基金会维护和支持。
MAT提供了一系列功能,可以帮助你识别和解决Java应用程序中的内存问题。它可以分析Java堆转储文件(通常是通过Java虚拟机的"-XX:+HeapDumpOnOutOfMemoryError"参数生成的)或运行时快照,并提供以下功能:
- 内存泄漏分析:MAT可以检测和分析内存泄漏,找出那些没有被正确释放的对象,从而导致内存占用过高的问题。
- 重复对象分析:MAT可以识别并分析堆内存中的重复对象,帮助你找出可能存在的冗余对象,并进行优化。
- 堆转储分析:MAT可以解析和分析Java堆转储文件,提供关于对象实例、类信息、引用关系和内存使用情况的详细信息。
- 内存使用统计:MAT提供了各种内存使用的统计信息,包括对象实例数量、内存占用大小、类加载器信息等,以帮助你了解应用程序的内存使用情况。
- 内存泄漏报告:MAT可以生成详细的内存泄漏报告,包括泄漏对象的路径、引用链和相关的堆转储信息,帮助你定位和解决内存泄漏问题。
下载地址:https://eclipse.dev/mat/downloads.php
小白手套熟练的将 Dump 文件下载到本地,并导入 MAT
翻译如下
OK,选择 Finish 后,就出现了一张简单的饼图
一眼可以看到,a 区域的内存占用达到 95 %,基本上可以定位到,问题是在这里开始的
这时,我们通过第一个利器,Histogram 来通过柱状图,展示每个类的实例数
介绍一下每一列的含义
按照分析图来看,java.lang.Object[]
最大,接下来,排除掉 Object[]
的软引用,看它的强引用
可以看到 tomcat 某个线程创建了 Object[] 数组,Ref. Shallow Heap(引用的浅堆大小): 420,781,224个,并且给数组重复填充了值 HeapOverflowExample
,
换句话来说,就是一个线程引用了大量的数组对象,占用了极大的内存,从而导致堆溢出,所以根据属性可以定位到程序的确是有不恰当的地方
Domain Tree 和 Histogram 类似,是通过对象栈的方式进行展示
遇到 OOM 问题不要慌,先及时恢复应用,将案发现场做好保存,事后分析即可,由于业务复杂性,可能查询方式不像这样容易,通过泄露报告定位大对象 + 强引用的思路,不会出错。
名词解释: