34-内存泄露MAT工具看本文就够了

一. 简介

欢迎关注公众号OpenCoder,来和我做朋友吧~

Eclipse Memory Analyzer是一个快速且功能丰富的Java堆分析器,可帮助您查找内存泄漏并减少内存消耗。使用Memory Analyzer分析具有数亿个对象的高效堆转储,快速计算对象的保留大小,查看谁阻止垃圾收集器收集对象,运行报告以自动提取泄漏嫌疑者。

通过MAT工具,可以做以下几方面的事儿:

  • 找到最大的对象,因为 MAT 提供了合理的累积大小(retained size)
  • 探索对象图,包括入站和出站引用
  • 计算从GC Roots 到有趣对象的路径
  • 查找内存浪费,如冗余 String 对象、空集合对象等...

二.下载地址

https://www.eclipse.org/mat/downloads.php

image

目前绝大多数开发工具都已经使用IDEA了,因此大家下载独立的MAT即可,注意:独立的MAT运行需要在JDK11及以上的环境。

三.Heap Dump

首先了解下Heap Dump,它也叫堆转储文件,是java进程在某个时间内的快照。它在触发快照的时候保存了很多信息:java对象和类信息。通常情况下,在写入堆转储之前会触发完整的 GC,因此它包含有关剩余对象的信息。

Memory Analyzer 能够处理来自各种平台的 HPROF 二进制堆转储、IBM 系统转储(旧版本需要预处理)和 IBM 便携式堆转储 (PHD)。

在Heap Dump中能得到的信息包括:(以下摘自官网)

Typical information which can be found in heap dumps (depending on the heap dump type):

  • All Objects

    Class, fields, primitive values and references

  • All Classes

    Classloader, name, super class, static fields

  • Garbage Collection Roots

    Objects defined to be reachable by the JVM

  • Thread Stacks and Local Variables

    The call-stacks of threads at the moment of the snapshot, and per-frame information about local objects

这里给大家翻译一下为:

可以在堆转储中找到的典型信息(取决于堆转储类型):

  • 所有对象
    类、字段、原始值和引用

  • All Classes

    类加载器、名称、超类、静态字段

  • 垃圾收集根对象GC Roots
    定义为可由 JVM 访问的对象(比如:局部变量和类静态变量)

  • 线程栈和局部变量
    快照时刻线程的调用堆栈,以及有关本地对象的每帧信息

四.怎样获取Dump

Dump文件的格式为:HPROF,内存分析器可以处理HPROF 二进制格式的堆转储

那么我们可以从以下几方面来获取Dump文件:

  • Non-interactive 被动获取:

    通过OOM获取,即在OutOfMemoryError后获取一份HPROF二进制Heap Dump文件,可以在jvm里添加参数:(除非真正发生 OOM,否则不涉及任何开销)

    -XX:+HeapDumpOnOutOfMemoryError
    

    这个参数对于生产系统来说是必须的,因为它通常是进一步分析内存泄露问题的唯一方法。

    默认情况下,堆转储将在 JVM 的“当前目录”中生成。它可以使用-XX:HeapDumpPath=显式重定向,例如-XX:HeapDumpPath=/disk2/dumps。请注意,转储文件可能很大,可达千兆字节,因此请确保目标文件系统有足够的空间。

  • Interactive 主动获取

    1. 在虚拟机中添加参数如下,然后在Ctrl+Break组合键即可获取一份Heap Dump:

      -XX:+HeapDumpOnCtrlBreak
      
  1. 通过 jmap 工具生成,在命令行中输入:

    jmap -dump:format=b file=<文件名XX.hprof> <pid>
    
  2. Sun JConsole:启动 jconsole.exe 并在 HotSpotDiagnostic MBean 上调用操作 dumpHeap()

  3. 使用Memory Analyzer Tools的File -> Acquire Heap Dump功能

image

图形化界面操作,直接选择想要dump的pid进程,设置存放文件的路径即可。

五.MAT使用

准备一份dump文件,通过MAT工具进行打开,在选好文件后,会让你选一下报告类型,默认是内存泄漏探测报告,没有什么特殊情况下,选它就可以了:

image

内存泄漏可疑点(Leak Suspects)

进入MAT后会展示内存泄漏可疑点在内存中的分布情况,还会列出具体的类,如果是自己的代码,基本上一眼大概就能定位到某些业务,如果还不能肯定,也没关系,接下来还有很多功能可以辅助分析

image

上图中Problem Suspect1 即代表可能出现内存泄露的问题分析:

The thread java.lang.Thread @ 0xff626d38 main keeps local variables with total size 7,293,920 (89.25%) bytes.

在线程的main中持续引用本地变量达到了 7.3M的内存,占用堆内存89.25%

The memory is accumulated in one instance of java.lang.Object[], loaded by <system class loader>, which occupies 7,292,936 (89.24%) bytes.

内存累积在一个“java.lang.Object[]”实例中,由“<system class loader>”加载,占用7,292,936 (89.24%)字节。说明的非常清晰,这个数组占据了大量的内存。

那么这个数组里到底是什么东西呢?

在上图中的左下角大家看到有一个 Details,大家点进去即可看到详细的说明:

image

通过Details我们可以看到,在主线程的下方引用了一个 java.util.ArrayList, 这里面是一个java.lang.Object[]数组,通过这里我们既可以清楚到底是什么对象占用了过大的内存,所以MAT分析内存是非常方便的。

六.追踪线程执行堆栈,找到问题代码

一旦发现在某个线程执行过程中创建了大量对象之后,就可以尝试找这个线程到底执行了哪些代码才创建了这些对象,我们可以点击下图中的“See stacktrace”

image

点击进去后即准确找到了发生问题的代码行数:

image

这里我们贴出对应的源代码,其实非常简单,如下:

image

代码问题就出现在了第10行,list添加元素这儿。

七. Histogram

刚才我们是在Leak Suspects中进行分析的,另外我们还可以打开一个非常常用的工具:Histogram

image

点击进去:

image

这里每一列的参数做一个解释:

  • Class Name : 类名称,java类名
  • Objects : 类的对象的数量,这个对象被创建了多少个
  • Shallow Heap :一个对象内存的消耗大小,不包含对其他对象的引用
  • Retained Heap :是shallow Heap的总和,也就是该对象被GC之后所能回收到内存的总和

可以看到Object[]这个数组就占据了7.4MB.

在某一项上右键打开菜单选择 list objects ->with incoming refs 将列出该类的实例:

image
image

大家可以发现通过这种方式也是能直观找到我们的大对象到底是什么。

好了,相信通过本篇文章的讲解,大家对于MAT工具的使用有了一定的理解和参考,后续遇到内存泄露、内存卡顿、大对象数据分析都可以直接通过MAT精准确定,更好的优化我们的项目。

欢迎关注公众号OpenCoder,来和我做朋友吧~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容