加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

内存泄露分析工具Memory Analyzer tool(MAT) 介绍

(2011-11-24 09:42:13)
标签:

杂谈

分类: 手机世界

 

Java如何管理内存

Java的内存管理就是对象的分配 和释放问题。在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。另外,对象的释放是由GC决定和执行的。在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线 的方法确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为,GC为了能够正确释放对象,GC必须 监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。

监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。

为了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向 被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有 向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。

以下,我们举一个例子说明内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况

以下右图,就是左边程序运行到第6行的示意图。

http://s7/bmiddle/5da93c8fgb271340d4e66&690Analyzer tool(MAT) 介绍" />


Java 使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。这种方式的 优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低 (很难处理循环引用的问题),但执行效率很高。

 

两种常见的内存泄露

1.永久保存区内存溢出

java.lang.OutOfMemoryError: PermGen space

Jvm默认的永久区为4M,如果未设置启动参数,很可能由于class类太多,导致永久区爆掉.设置set JAVA_OPTS=-Xms800m -Xmx800m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m

设置-XX:PermSize 可以解决这个问题

 

2.JVM调配使用的内存空间不足内存溢出

GC可用heapsize不足2%时抛出,java.lang.OutOfMemoryError: Java heap space

 

MAT工具能够解决那些问题?

1. 快速查找解决系统崩溃.

2. 能够看到系统运行情况,提前找到系统内存使用上存在的问题.

 

如何使用

dump出内存,可以通过MAT工具分析内存使用情况,找到问题的关键.

 

案例介绍

设置jvm启动参数

    增加set JAVA_OPTS= -verbose:gc -Xloggc:../logs/gclog.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistributio-XX:+HeapDumpOnOutOfMemoryError  %JAVA_OPTS%

 

加在jboss 的 run.bat 98.加在使用JAVA_OPTS 前面就行了

其中红色标记的是内存溢出时内存状况写入到文件中.

 

写一段非常好资源的代码.

    protected void execute(RunData rundata, TemplateContext context) throws WebxException {

        

        this.test();

        

        

    }

    

    private void test(){

      //创建一个非常耗性能的代码

        List<String> ret1 new ArrayList<String>();

        List<String> ret2 new ArrayList<String>();

        List<String> ret3 new ArrayList<String>();

        List<String> ret4 new ArrayList<String>();

        List<String> ret5 new ArrayList<String>();

        String tmp "";

        for(int j=0;j<1000000;j++){

            tmp tmp+String.valueOf(j);

            ret1.add(tmp);

            ret2.add(tmp);

            ret3.add(tmp);

            ret4.add(tmp);

            ret5.add(tmp);

        }

    }

    

 

部署应用,通过链接,运行这段代码.

 

结果出来了.

http://s14/bmiddle/5da93c8fgb2713917947d&690Analyzer tool(MAT) 介绍" />

 

Dump的结果在jbossbin目录下.

 

分析:

使用mat,打开这个文件.

http://s9/bmiddle/5da93c8fgb27139b01488&690Analyzer tool(MAT) 介绍" />

可以看到内存实际使用情况.

 

http://s1/bmiddle/5da93c8fgb2713a452c70&690Analyzer tool(MAT) 介绍" />

 

某一块内存使用情况.

http://s15/bmiddle/5da93c8fgb2713add214e&690Analyzer tool(MAT) 介绍" />

 

 

 

http://s13/bmiddle/5da93c8fgb2713b95735c&690Analyzer tool(MAT) 介绍" />


 

下面出错的堆栈,可以看出问题到底是出在什么地方.

 http://s14/middle/5da93c8fgb2713fa3228d&690Analyzer tool(MAT) 介绍" TITLE="内存泄露分析工具Memory Analyzer tool(MAT) 介绍" />

 

还可以使用jmap的命令dump出内存情况然后进行分析

使用 jmap -dump:format=b,file=xxx.hprof  java进程id

 

Dump出来的内存情况,直接用mat工具打开即可.

 

相关资料:

http://www.blogjava.net/rosen/archive/2011/01/26/321575.html

http://www.cnblogs.com/wangtianxj/archive/2010/10/19/1855751.html

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有