@frank-shaw
2015-11-07T08:38:23.000000Z
字数 2788
阅读 7545
java.内存
关于Eclipse Memory Analyzer的安装,网上有很多教程,我选择的是直接通过Eclipse插件的形式安装最新的Memory Analyzer。步骤如下:
打开eclipse->Help->Install new software->work with右边的Add...显示下图:
这里使用的网址是:http://download.eclipse.org/mat/1.5/update-site/
具体版本下载地址可以参考下面的网址 http://www.eclipse.org/mat/downloads.php
很简单的安装步骤不是么。接下来看看如何使用。
Memory Analyzer主要分析的是内存的使用情况,它能够打开的是.hprof格式的文件。为了得到该文件,我们先写好如下简单代码:
package memoryManage;
import java.util.*;
/*
* 根据书本2.4.1章节的代码书写
* VM args: -Xms20m -Xmx20M -XX:+HeapDumpOnOutOfMemoryError
*/
public class HeapOOM {
int num;
public HeapOOM() {
num = 100000;
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
List<HeapOOM> list = new ArrayList<HeapOOM>();
while(true)
list.add(new HeapOOM());
}
}
很简单不是么,为了让内存溢出罢了。不过先不要运行该程序,需要进行相应的设置之后才会有.hprof格式的文件生成。请看下图:
打开该程序的Debug Configurations之后,可以看到下图:
此时点击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,点击确定,那么就可以运行上面的程序,最后控制台输出如下:
这个时候,可以发现,已经生成了java_pid11072.hprof文件。那么,我们就可以尝试着去通过我们下载好的Memory Analyzer去分析了。我们通过下面的方式打开该文件:点击file的open file
找到存放本程序的文件夹,可以发现有这个java_pid11072.hprof文件,打开即可。
打开之后,是这个样子的。
当然,我们可以很容易发现这个程序的问题,在Memory Analyzer的诊断中也给了我们提醒:
截图的意思是说:主线程的局部变量占据了太多的内存,达到了97.36%。实际上,一个ListArray自身占据不了多少内存,注意是其中的实例对象在一直创建,每创建一个对象就要放置到堆内存里面去,由此导致了堆内存溢出。
例子中的问题自然好办,我们自己也可以查找出来。但是我们想使用Memory Analyzer做一些更多的工作,真正帮助我们排查出内存问题。那么我们就需要好好研究研究一番这个该怎么弄。
推荐一个英文网址:http://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/
你很快就会在浏览的时候发现这两个词,那么它们是什么意思呢?
参考的是:http://bjyzxxds.iteye.com/blog/1532937
对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。
Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。
我们先来看看截图信息,加深对以上意思的理解:
截图可以看到,main线程自身占用的内存只不过是120Byte,但是如果将main线程GC掉之后,可以去除掉16,207,160Byte,也就是说有极大部分的内存是与其相关联的。只要找到一个办法去掉它的话,那可真的是大快人心啊(别傻,main线程没了怎个程序就没了,别闹哈)
同样的,让我们来看看memoryManage.HeapOOM @ 0xfec00000这个对象,它占用的内存是16Byte,但是它的Retained Heap也是16Byte。说明该项并不会导致内存问题。
实际上,上图演示的就是一颗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,得到该对象所对应的类(并不是该对象,值得注意)到GC Roots 的路径(有各种选项供选择):
比如上图的memoryManage.HeapOOM @ 0xfec00000,可以看到它有两条路径通往GC Roots:
这个选项在必要的时候非常有用,可以让你看清楚这个类与周围的关联性。
就介绍到这里了,没有太多的项目经验,只能对着别人的资料瞎说一阵。等有了更深刻的经验之后,再来补充吧。