[关闭]
@frank-shaw 2015-11-07T00:38:23.000000Z 字数 2788 阅读 7131

内存管理工具Memory Analyzer的使用

java.内存


安装

关于Eclipse Memory Analyzer的安装,网上有很多教程,我选择的是直接通过Eclipse插件的形式安装最新的Memory Analyzer。步骤如下:

  1. 打开eclipse->Help->Install new software->work with右边的Add...显示下图:
    M1.png-7.5kB
    这里使用的网址是:http://download.eclipse.org/mat/1.5/update-site/
    具体版本下载地址可以参考下面的网址 http://www.eclipse.org/mat/downloads.php

    1. 出现如下界面的时候,对应部分选上,然后一直下一步就可以了。

      不过插件形式的安装需要等待比较久的时间。不过还是可以安装好的。

很简单的安装步骤不是么。接下来看看如何使用。

使用

Memory Analyzer主要分析的是内存的使用情况,它能够打开的是.hprof格式的文件。为了得到该文件,我们先写好如下简单代码:

  1. package memoryManage;
  2. import java.util.*;
  3. /*
  4. * 根据书本2.4.1章节的代码书写
  5. * VM args: -Xms20m -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
  6. */
  7. public class HeapOOM {
  8. int num;
  9. public HeapOOM() {
  10. num = 100000;
  11. // TODO Auto-generated constructor stub
  12. }
  13. public static void main(String[] args) {
  14. List<HeapOOM> list = new ArrayList<HeapOOM>();
  15. while(true)
  16. list.add(new HeapOOM());
  17. }
  18. }

很简单不是么,为了让内存溢出罢了。不过先不要运行该程序,需要进行相应的设置之后才会有.hprof格式的文件生成。请看下图:
m2.png-51.6kB
打开该程序的Debug Configurations之后,可以看到下图:
m3.png-45.4kB
此时点击Arguments,设置VM参数为:
-verbose:gc -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError

参数含义:

–verbose:gc 在虚拟机发生内存回收时在输出设备显示信息,格式如下: [Full GC 268K->168K(1984K), 0.0187390 secs]该参数用来监视虚拟机内存回收的情况。
-Xms20M 设置应用程序的初始内存大小为20M
-Xmx20M 设置应用程序的能够使用的最大内存为20M(与-Xms设置大小相同可以避免堆自动扩展)
-XX:+HeapDumpOnOutOfMemoryError 可以让虚拟机在出现内存异常的时候自动Dump出当前的内存对转储快照以便日后进行分析

设置好了之后,点击apply,点击确定,那么就可以运行上面的程序,最后控制台输出如下:
m4.png-30.5kB

这个时候,可以发现,已经生成了java_pid11072.hprof文件。那么,我们就可以尝试着去通过我们下载好的Memory Analyzer去分析了。我们通过下面的方式打开该文件:点击file的open file
m6.png-6.7kB
找到存放本程序的文件夹,可以发现有这个java_pid11072.hprof文件,打开即可。
m5.png-50.4kB
m7.png-20.2kB

打开之后,是这个样子的。
m8.png-25.6kB

分析性能

当然,我们可以很容易发现这个程序的问题,在Memory Analyzer的诊断中也给了我们提醒:
m9.png-12.1kB

截图的意思是说:主线程的局部变量占据了太多的内存,达到了97.36%。实际上,一个ListArray自身占据不了多少内存,注意是其中的实例对象在一直创建,每创建一个对象就要放置到堆内存里面去,由此导致了堆内存溢出。

例子中的问题自然好办,我们自己也可以查找出来。但是我们想使用Memory Analyzer做一些更多的工作,真正帮助我们排查出内存问题。那么我们就需要好好研究研究一番这个该怎么弄。

推荐一个英文网址:http://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/

Shallow heap vs Retained heap

你很快就会在浏览的时候发现这两个词,那么它们是什么意思呢?
参考的是:http://bjyzxxds.iteye.com/blog/1532937

Shallow Size

对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。

Retained Size

Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。

我们先来看看截图信息,加深对以上意思的理解:
m10.png-23.4kB
截图可以看到,main线程自身占用的内存只不过是120Byte,但是如果将main线程GC掉之后,可以去除掉16,207,160Byte,也就是说有极大部分的内存是与其相关联的。只要找到一个办法去掉它的话,那可真的是大快人心啊(别傻,main线程没了怎个程序就没了,别闹哈)

同样的,让我们来看看memoryManage.HeapOOM @ 0xfec00000这个对象,它占用的内存是16Byte,但是它的Retained Heap也是16Byte。说明该项并不会导致内存问题。

Dominator 树视图

实际上,上图演示的就是一颗Dominator 树视图,通过它可以更加理解Retained Heap。在垃圾回收机制中有一个GC Roots,它其实就是这棵树的根root。

An Object X is said to dominate an Object Y if every path from the Root to Y must pass through X. Looking at the dominator tree for our example, we can start to see where the bulk of our memory is leaking.

Path to GC Roots

我们针对某一个对象,可以点击右键,然后点击Path to GC Roots,得到该对象所对应的类(并不是该对象,值得注意)到GC Roots 的路径(有各种选项供选择):
m11.png-44kB

比如上图的memoryManage.HeapOOM @ 0xfec00000,可以看到它有两条路径通往GC Roots:
m12.png-15.7kB

这个选项在必要的时候非常有用,可以让你看清楚这个类与周围的关联性。

结语

就介绍到这里了,没有太多的项目经验,只能对着别人的资料瞎说一阵。等有了更深刻的经验之后,再来补充吧。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注