Tomcat内存优化4.1 内存泄漏——内存分析工具 MAT 的使用

在eclipse安装、使用MAT插件


简介: 
Eclipse提供的一个内存分析工具。它是一个功能丰富的 JAVA 堆转储文件分析工具,可以帮助你发现内存漏洞和减少内存消耗。
官网地址:http://www.eclipse.org/mat 

安装 (如果你使用的是MOTODEV Studio for Android则默认自带了该工具)
你可以选择安装Eclipse提供的原版插件或使用MOTODEV Studio for Android插件

>>1.原版插件 
1).启动Eclipse,一次点击Help -> Intall New Software...;
2).点击输入栏右侧小箭头,选择"Galileo"(我的是3.5版,不同版本要找到和自己版本名称对应的);
3).等待列表更新完毕,找到并展开"General Purpose Tools";
4).选中并下载其中的"Memory Analyser (Incubation)"和"Memory Analyser (Charts)"两项。

>>2.MOTODEV Studio for Android插件 
1).启动Eclipse,一次点击Help -> Intall New Software...;
2).通过Add新建一个更新(最新地址可在此 获得):
    Name:MOTODEV Studio for Android Plugin
    Location:https://studio-android.motodevupdate.com/android/2.0
3).下载并安装此更新。
* 如果主要针对Android开发,建议使用MOTODEV Studio for Android的整合插件,应为它还提供了很多便利的工具,不过如果已经安装了ADT的需要先手动卸载才能安装,具体请参考:作为插件安装 MOTODEV Studio。

使用方式1 —— 带参数运行 
具体可参考:Eclipse Memory Analyser (MAT) - Tutorial
归纳的大致步骤:
(1) 在Run Conigurations..中的Arguments设置VM argument为:
-XX:+HeapDumpOnOutOfMemoryError
(2) 运行你的项目并生成.hprof文件,如果没看到请按F5刷新项目目录,就在根目录下;
(3) 双击.hprof文件打开,选择"Leak Suspects Report"

使用方式2 —— 结合Sequoyah监控特定的设备及应用
<该方式需要你安装了Sequoyah 或MOTODEV Studio for Android插件>

具体可参考:使用MAT分析应用内存

--------------------------------------------------------
*注意: 
解析过大的HeapDump可能会导致Eclipse抛出OutOfMemory的错误:

 
这时你需要手动调整Eclipse的缓存大小,可参考官网给出的处理方式(原文链接 ):

 
>>我的使用情况: 
我的机器只能设到512m,而且始终没法解决OutOfMemory的问题,看来对内存有一定要求呐...

但是我下载了RPC版的MAT却是能正常打开的,Eclipse插件版打不开的朋友可以试试该方式:RPC版MAT下载地址
--------------------------------------------------------

打开后的界面如下: 


更详细的使用示例请参考以下文章: 
http://wiki.eclipse.org/index.php/MemoryAnalyzer
—— 官方的帮助文档

使用 Eclipse Memory Analyzer 进行堆转储文件分析
—— 来自IBM的使用教程

Eclipse Memory Analyser (MAT) - Tutorial
—— 一个浅显易懂的MAT使用教程

使用Memory Analyzer tool(MAT)分析内存泄漏(一)
使用Memory Analyzer tool(MAT)分析内存泄漏(二)
—— 详细地分析了内存泄露的原因,并举例说明,强烈推荐


有关MAT插件的介绍请看:

安装MAT插件的地址是:http://download.eclipse.org/mat/1.1/update-site

当点击下一步的时候出现:

Cannot complete the install because one or more required items could not be found.
Software being installed: Memory Analyzer RCP 1.1.1.201108240735 (org.eclipse.mat.ui.rcp.feature.feature.group 1.1.1.201108240735)
Missing requirement: Memory Analyzer Help 1.1.1.201108240735 (org.eclipse.mat.ui.help 1.1.1.201108240735) requires 'bundle org.eclipse.help.appserver 3.1.200' but it could not be found
Cannot satisfy dependency:
From: Memory Analyzer RCP 1.1.1.201108240735 (org.eclipse.mat.ui.rcp.feature.feature.group 1.1.1.201108240735)
To: org.eclipse.mat.ui.help [1.1.1.201108240735]

将地址改为:http://archive.eclipse.org/mat/1.2/update-site

安装成功!

使用:


在工作中可能会遇到内存溢出这种灾难性的问题,那么程序肯定是存在问题,找出问题至关重要,上一篇文章讲了jmap命令的使用方法,当然用jmap导出的 文件我们也看不懂啊,那就交给memory analyzer(mat)这个工具,让他帮助我们来观察程序的内存分布情况吧。

    MAT 不是一个万能工具,它并不能处理所有类型的堆存储文件。但是比较主流的厂家和格式,例如 Sun, HP, SAP 所采用的 HPROF 二进制堆存储文件,以及 IBM 的 PHD 堆存储文件等都能被很好的解析。下面来看看要怎么做呢,也许对你有用。官方文档:http://help.eclipse.org/luna/index.jsp?topic=/org.eclipse.mat.ui.help/welcome.html

造成OutOfMemoryError原因一般有2种:

1、内存泄露,对象已经死了,无法通过垃圾收集器进行自动回收,通过找出泄露的代码位置和原因,才好确定解决方案;
2、内存溢出,内存中的对象都还必须存活着,这说明Java堆分配空间不足,检查堆设置大小(-Xmx与-Xms),检查代码是否存在对象生命周期太长、持有状态时间过长的情况。


1. 用jmap生成堆信息

Java程序内存分析:使用mat工具分析内存占用

这样在E盘的jmap文件夹里会有一个map.bin的堆信息文件 

2. 将堆信息导入到mat中分析   

Java程序内存分析:使用mat工具分析内存占用

 


3. 生成分析报告

    mat可以为我们生成多个报告:

    Java程序内存分析:使用mat工具分析内存占用    Java程序内存分析:使用mat工具分析内存占用

    Java程序内存分析:使用mat工具分析内存占用    Java程序内存分析:使用mat工具分析内存占用

 

    下面来看看生成的这些数据对我们有什么帮助

    Java程序内存分析:使用mat工具分析内存占用

    从上图可以看到它的大部分功能,在饼图上,你会发现转储的大小和数量的类,对象和类加载器。
正确的下面,饼图给出了一个印象最大的对象转储。移动你的鼠标一片看到对象中的对象的细节检查在左边。下面的Action标签中:

  • Histogram可以列出内存中的对象,对象的个数以及大小。

  • Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。

  • Top consumers通过图形列出最大的object。

  • Leak Suspects通过MA自动分析泄漏的原因。

Histogram

    Java程序内存分析:使用mat工具分析内存占用

  • Class Name : 类名称,java类名

  • Objects : 类的对象的数量,这个对象被创建了多少个

  • Shallow Heap :一个对象内存的消耗大小,不包含对其他对象的引用

  • Retained Heap :是shallow Heap的总和,也就是该对象被GC之后所能回收到内存的总和


一般来说,Shallow Heap堆中的对象是的大小和保留内存大小相同的对象是堆内存的数量时,将释放对象被垃圾收集。
保 留设置一组主要的对象,例如一个特定类的所有对象,或所有对象的一个特定的类装入器装入的类或者只是一群任意对象,是释放的组对象如果所有对象的主要设置 变得难以接近的。保留设置包括这些对象以及所有其他对象只能通过这些对象。保留大小是总堆大小中包含的所有对象的保留。摘自eclipse


关于的详细讲解,建议大家查看Shallow heap & Retained heap,这是个很重要的概念。

Java程序内存分析:使用mat工具分析内存占用

这儿借助工具提供的regex正则搜索一下我们自己的类,排序后看看哪些相对是占用比较大的。

Java程序内存分析:使用mat工具分析内存占用

左边可以看到类的详细使用,比如所属包,父类是谁,所属的类加载器,内存地址,占用大小和回收情况等

Java程序内存分析:使用mat工具分析内存占用

这儿有个工具可以根据自己的需求分组查找,默认根据class分组,类似我们sql里的group by了~~

Java程序内存分析:使用mat工具分析内存占用

这里可以看到上面3个选项,分别生成overview、leak suspects、top components数据,但是这儿生成的不是图表,如果要看图表在Java程序内存分析:使用mat工具分析内存占用(Overview)中的Action标签里点击查看。

这个是Overview中的 Heap Dump Overview视图,从工具栏中点开,这是一个全局的内存占用信息

Used heap dump 79.7 MB
Number of objects 1,535,626
Number of classes 8,459
Number of class loaders 74
Number of GC roots 2,722
Format hprof
JVM version
Time 格林尼治标准时间+0800上午9时20分37秒
Date 2014-7-2
Identifier size 32-bit
File path E:\jmap\map.bin
File length 108,102,005
  • Total: 12 entries


然后可以点开SystemProperties和Thread Overview进行查看,我这里就不贴了内容比较多。

Dominator Tree

Java程序内存分析:使用mat工具分析内存占用

我们可以看到ibatis占了较多内存

Top consumers

Java程序内存分析:使用mat工具分析内存占用

这张图展示的是占用内存比较多的对象的分布,下面是具体的一些类和占用。

150945_hmjj_1767531.png

按等级分布的类使用情况,其实也就是按使用次数查看,java.lang.Class被排在第一

151054_d2q1_1767531.png

还有一张图是我们比较关心的,那就是按包名看占用,根据包我们知道哪些公共用的到jar或自己的包占用

Java程序内存分析:使用mat工具分析内存占用

这样就可以看到包和包中哪些类的占用比较高。

Leak Suspects

Java程序内存分析:使用mat工具分析内存占用

这份报告,看到该图深色区域被怀疑有内存泄漏,可以发现整个heap只有79.7M内存,深色区域就占了62%。所以,MAT通过简单的报告就说明了项目是有可疑代码的,具体点开详情来找到类

Java程序内存分析:使用mat工具分析内存占用

Java程序内存分析:使用mat工具分析内存占用

Java程序内存分析:使用mat工具分析内存占用

点击鼠标,在List Objects-> with outgoing references下可以查看该类都引用了什么对象,由此查看是否因为其他对象导致的内存问题。

下面继续查看pool的gc ROOT

如下图所示的上下文菜单中选择 Path To GC Roots -> exclude weak references, 过滤掉弱引用,因为在这里弱引用不是引起问题的关键。

进入查看即可,我这儿的代码没有问题,就不用贴了。

Java程序内存分析:使用mat工具分析内存占用


The classloader/component "org.apache.catalina.loader.WebappClassLoader @ 0xa34cde8" occupies 19,052,864 (22.80%) bytes. The memory is accumulated in one instance of "java.util.HashMap$Entry[]" loaded by "".

Keywords
java.util.HashMap$Entry[]
org.apache.catalina.loader.WebappClassLoader @ 0xa34cde8


这段话是在工具中提示的,他告诉我们WebappClassLoader占了19,052,864 字节的容量,这是tomcat的类加载器,JDK自带的系统类加载器中占用比较多的是HashMap。这个其实比较正常,大家经常用map作为存储容器。

除了在上一页看到的描述外,还有Shortest Paths To the Accumulation Point和Accumulated Objects部分,这里说明了从GC root到聚集点的最短路径,以及完整的reference chain。观察Accumulated Objects部分,java.util.HashMap的retained heap(size)最大,所以明显类实例都聚集在HashMap中了。

Java程序内存分析:使用mat工具分析内存占用

来看看Accumulated Objects by Class区域,这里能找到被聚集的对象实例的类名。java.util.HashMap类上头条了,被实例化了5573次,从这儿看出这个程序不存在什 么问题,因为这个数字是比较正常的,但是当出问题的时候我们都会看到比较大的自定义类会在前面,而且占用是相当高。

当然,mat这个工具还有很多的用法,这里把我了解的分享给大家,不管如何,最终我们需要得出系统的内存占用,然后对其进行代码或架构,服务器的优化措施!

参考文献:

http://www.eclipse.org/mat/about/screenshots.php

http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/

来自:http://my.oschina.net/biezhi/blog/286223



阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页