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

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

形成OutOfMemoryError缘由通常有2种:html

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


1. 用jmap生成堆信息

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

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


3. 生成分析报告

    mat能够为咱们生成多个报告:apache

        

        


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

    

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

    • Histogram能够列出内存中的对象,对象的个数以及大小。架构

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

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

    • Leak Suspects经过MA自动分析泄漏的缘由。

    Histogram

        

    • Class Name : 类名称,java类名

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

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

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


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


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

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

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

    这儿有个工具能够根据本身的需求分组查找,默认根据class分组,相似咱们sql里的group by了~~

    这里能够看到上面3个选项,分别生成overview、leak suspects、top components数据,可是这儿生成的不是图表,若是要看图表在(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

    咱们能够看到ibatis占了较多内存

    Top consumers

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

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

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

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

    Leak Suspects

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

    点击鼠标,在List Objects-> with outgoing references下能够查看该类都引用了什么对象,由此查看是否由于其余对象致使的内存问题。

    下面继续查看pool的gc ROOT

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

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


    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 "<system class loader>".

    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中了。

    来看看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/

相关文章
相关标签/搜索