大部分 初级程序员 面对内存溢出的dump总是无从下手,觉得必须要资深的大神才能破解内存溢出这个难题,其实排查内存溢出并非难事,你离你心目中的大神只差以下这两个工具而已。
Eclipse Memory Analyzer(MAT)
Eclipse Memory Analyzer(简称MAT)是一个功能丰富且操作简单的JVM Heap Dump分析工具,可以用来辅助发现内存泄漏减少内存占用。
使用 Memory Analyzer 来分析生产环境的 JAVA 堆转储文件,可以从数以百万计的对象中快速计算出对象的 Retained Size,查看是谁在阻止垃圾回收,并自动生成一个 Leak Suspect( 内存泄露 可疑点)报表。
下载地址:
以下尝试给大家分析一个简单的案例
启动软件
选择一个OOM时刻生成的dump文件,选择Leak Supspects Report,点击Finish
主界面
如果dump较大建议调高MAT启动时的内存参数,分析大概消耗几十秒到几分钟不等,分析后显示如下界面
Histogram 直方图
在overview界面选择Histogram可以列出每个类产生的实例数量,以及所占用的内存大小和 百分比 。主界面如下图所示:
图中 Shallow Heap 和 Retained Heap 分别表示对象自身不包含引用的大小和对象自身并包含引用的大小。默认的大小单位是 Bytes ,可以在 Window – Preferences 菜单中设置单位,图中设置的是KB。
图中画红线的部位为一个自定义的PO类 ,相信大部分同学看到这里都会眼前一亮,这就是罪魁祸首吗?不急接着往下看
Dominator Tree视图
打开Dominator Tree(支配树)视图,在此视图中列出了每个对象(Object Instance)与其引用关系的树状结构,同时包含了占用内存的大小和百分比。
支配树和直方图类似,只不过他是以对象树的形式展示出来,上图可以看出占用空间最多的就是java.lang.Thread, 通过点击查看子节点后可以看到内存存放最多的还是上面分析出来的自定义PO对象
定位溢出源
Histogram视图和Dominator Tree视图的角度不同,前者是基于类的角度,后者是基于对象实例的角度,并且可以更方便的看出其引用关系。
首先,在两个视图中找出疑似溢出的对象或者类(可以通过Retained Heap排序,并且可以在Class Name中输入正则表达式的关键词只显示指定的类名),然后右键选择Path To GC Roots(Histogram中没有此项)或Merge Shortest Paths to GC Roots,然后选择 exclude all phantom/weak/soft etc. reference :
GC Roots意为GC根节点,其含义见上面的 GC Roots和Reference Chain 部分,后面的 exclude all phantom/weak/soft etc. reference 意思是排除虚引用、弱引用和软引用,即只剩下强引用,因为除了强引用之外,其他的引用都可以被JVM GC掉,如果一个对象始终无法被GC,就说明有强引用存在,从而导致在GC的过程中一直得不到回收,最终就内存溢出了。
通过排查后得出结论 :由于启动了多个线程执行过程中产生出了大量无法回收的PO对象。结合自身业务代码,可以快速的断定出导致内存溢出的相关代码
HeapHero
HeapHero是堆转储分析工具。除了进行传统的堆转储分析之外,还能生成对应的内存浪费报告。主要针对以下方面进行检测:重复 字符串 ,重复对象,低效集合,等等。HeapHero检测这些低效的问题以及它们在源代码中的起源点。
官网:
篇幅有限HeapHero的案例教程过几天抽空奉上, 如果同学觉得这篇文章对你有帮助,还请点赞、评论捧场~ ,大家可以在评论区留言想学习哪方面的知识( JAVA、大数据相关 ),我会抽空写出相关的文章供大家学习,需要学习视频的可私信我回复“ 大数据 ”