MemoryAnalyzer补充

首先,以前在网上下载的是Myeclipse的插件 --memory analyzer,在网站的下面是Memory Analyzer的单机版,单机版安装简单,适合平常操做。下载地址:http://www.eclipse.org/mat/do...
以前一直纠结如何获取一个Java项目的内存分析的hprof文件,网上找了不少博客都是一笔带过(这个很容易?!),最后多是搜索恰当,用JVM指令:php

jmap -dump:format=b,file=文件名.hprof[pid]

导出内存信息文件,而后利用Memory Analyzer工具打开进行内存分析(对于内存泄露,OOM等分析有很大的帮助)。java

分析三步曲

一般咱们都会采用下面的“三步曲”来分析内存泄露问题:eclipse

  • 首先,对问题发生时刻的系统内存状态获取一个总体印象。
  • 第二步,找到最有可能致使内存泄露的元凶,一般也就是消耗内存最多的对象
  • 接下来,进一步去查看这个内存消耗大户的具体状况,看看是否有什么异常的行为

工具

下面将用一个基本的例子来展现如何采用“三步曲”来查看生产的分析报告。网站

查看报告之一:内存消耗的总体情况

图 7. 内存泄露分析报告
图片描述spa

如图 7 所示,在报告上最醒目的就是一张简洁明了的饼图,从图上咱们能够清晰地看到一个可疑对象消耗了系统 99% 的内存。在图的下方还有对这个可疑对象的进一步描述。咱们能够看到内存是由java.util.Vectorcom.ibm.oti.vm.BootstrapClassLoader 负责这个对象的加载。这段描述很是短,但我相信您已经能够从中找到不少线索了,好比是哪一个类占用了绝大多数的内存,它属于哪一个组件等等。
接下来,咱们应该进一步去分析问题,为何一个 Vector 会占据了系统 99% 的内存,谁阻止了垃圾回收机制对它的回收。插件

查看报告之二:分析问题的所在

首先咱们简单回顾下 JAVA 的内存回收机制,内存空间中垃圾回收的工做由垃圾回收器 (Garbage Collector,GC) 完成的,它的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,若是对象正在被引用,那么称其为存活对象,反之,若是对象再也不被引用,则为垃圾对象,能够回收其占据的空间,用于再分配。
在垃圾回收机制中有一组元素被称为根元素集合,它们是一组被虚拟机直接引用的对象,好比,正在运行的线程对象,系统调用栈里面的对象以及被 system class loader 所加载的那些对象。堆空间中的每一个对象都是由一个根元素为起点被层层调用的。所以,一个对象还被某一个存活的根元素所引用,就会被认为是存活对象,不能被回收,进行内存释放。所以,咱们能够经过分析一个对象到根元素的引用路径来分析为何该对象不能被顺利回收。若是说一个对象已经不被任何程序逻辑所须要可是还存在被根元素引用的状况,咱们能够说这里存在内存泄露。
如今,让咱们开始真正的寻找内存泄露之旅,点击“Details ”连接,能够看到如图 8 所示对可疑对象 1 的详细分析报告。
图 8. 可疑对象 1 的详细分析报告
图片描述线程

咱们查看下从 GC 根元素到内存消耗汇集点的最短路径:
图 9. 从根元素到内存消耗汇集点的最短路径
图片描述code

咱们能够很清楚的看到整个引用链,内存汇集点是一个拥有大量对象的集合,若是你对代码比较熟悉的话,相信这些信息应该能给你提供一些找到内存泄露的思路了。
接下来,咱们再继续看看,这个对象集合里到底存放了什么,为何会消耗掉如此多的内存。
图 10. 内存消耗汇集对象信息
图片描述orm

在这张图上,咱们能够清楚的看到,这个对象集合中保存了大量 Person 对象的引用,就是它致使的内存泄露。
至此,咱们已经拥有了足够的信息去寻找泄露点,回到代码,咱们发现,是下面的代码致使了内存泄露 :
清单 1. 内存泄漏的代码段

while (1<2) 
{ 
            
    Person person = new Person("name","address",i); 
    v.add(person); 
    person = null; 
}

总结

从上面的例子咱们能够看到用 MAT 来进行堆转储文件分析,寻找内存泄露很是简单,尤为是对于新手而言,这是一个很好的辅助分析工具。可是,MAT 绝对不单单是一个“傻瓜式”内存分析工具,它还提供不少高级功能,好比 MAT 支持用 OQL(Object Query Language)heap dump 中的对象进行查询,支持对线程的分析等,有关这些功能的使用能够参考 MAT 的帮助文档。

相关文章
相关标签/搜索