在定位一线问题时经常碰测试中出现Out Of Memory的问题, 通过jmap查看,发现JVM heap全用满了。有很多工具可以查看JVM堆的信息, 收费的比如JProfiler, YourKit,免费的如Oracle JDK自带的visualvm, jhat和Eclipse MAT。这个应用安装在一台AWS上,没有图形界面, 内存也比较小,想通过VNC远程桌面启动visualvm或者MAT不可能,通过jhat分析dump出来的snapshot(大约4.3G)也很慢,半天没有分析完毕,这种办法也放弃。

最后通过MAT的命令行工具分析了dump出来的snapshot,查找到OOM的元凶。

一、使用脚本分析Dump文件

如果没有办法图形化启动visualvm和MAT,那么就使用MAT文件夹下的ParseHeapDump.sh, 特别适合分析大堆的信息
  首先你需要修改MemoryAnalyzer.ini中的Xmx值,确保有充足的硬盘空间(至少dump文件的两倍)。然后运行:

  ./ParseHeapDump.sh heap.bin org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components

会得到suspects, overview和top_components三个视图的信息:

可以看到akka.dispatch.Dispatcher$$anon$1一个实例占用了2.4GB的内存,这就是罪魁祸首。这其实是akka dispatcher的mailbox中java.util.concurrent.ConcurrentLinkedQueue,每个Node占用了81M的内存,消息体太大了。

二、编写程序得到所需信息

也可以引 MAT的类,得到heap dump中的信息, 因为MAT使用Eclipse RCP框架, 基于osgi架构,使用起来不太方便,所以你可以别人抽取出来的MAT库,如https://bitbucket.org/joebowbeer/andromat,然后实现一个命令行程序,比如下面的例子就是输出所有的字符串的值:

import org.eclipse.mat.SnapshotException;
import org.eclipse.mat.parser.model.PrimitiveArrayImpl;
import org.eclipse.mat.snapshot.ISnapshot;
import org.eclipse.mat.parser.internal.SnapshotFactory;
import org.eclipse.mat.snapshot.model.IClass;
import org.eclipse.mat.snapshot.model.IObject;
import org.eclipse.mat.util.ConsoleProgressListener;
import org.eclipse.mat.util.IProgressListener; import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap; public class Main {
public static void main(String[] args) throws SnapshotException, IOException {
String arg = args[args.length - 1];
String fileName = arg;
IProgressListener listener = new ConsoleProgressListener(System.out);
SnapshotFactory sf = new SnapshotFactory();
ISnapshot snapshot = sf.openSnapshot(new File(fileName),new HashMap<String, String>(), listener);
System.out.println(snapshot.getSnapshotInfo());
System.out.println();
String[] classNames = {"java.lang.String"};
for (String name : classNames) {
Collection<IClass> classes = snapshot.getClassesByName(name, false);
if (classes == null || classes.isEmpty()) {
System.out.println(String.format("Cannot find class %s in heap dump", name));
continue;
}
assert classes.size() == 1;
IClass clazz = classes.iterator().next();
int[] objIds = clazz.getObjectIds();
long minRetainedSize = snapshot.getMinRetainedSize(objIds, listener);
System.out.println(String.format("%s instances = %d, retained size >= %d", clazz.getName(), objIds.length, minRetainedSize));
for (int i = 0; i < objIds.length; i++) {
IObject str = snapshot.getObject(objIds[i]);
String address = Long.toHexString(snapshot.mapIdToAddress(objIds[i]));
PrimitiveArrayImpl chars = (PrimitiveArrayImpl) str.resolveValue("value");
String value = new String((char[]) chars.getValueArray());
System.out.println(String.format("id=%d, address=%s, value=%s", objIds[i], address, value)); }
}
}
}

基本上使用ParseHeapDump.sh已经得到了我所需要的结果,优化akka actor消息的内容解决了我的问题。

三、mat常见功能的使用

1、Histogram 查询

用的最多的功能是 Histogram,点击 Actions下的  Histogram项将得到 Histogram结果:

它按类名将所有的实例对象列出来,可以点击表头进行排序,在表的第一行可以输入正则表达式来匹配结果 :

在某一项上右键打开菜单选择 list objects ->with incoming refs 将列出该类的实例:

它展示了对象间的引用关系,比如展开后的第一个子项表示这个 HomePage(0x420ca5b0)被 HomePageContainer(0x420c9e40)中的  mHomePage属性所引用.

快速找出某个实例没被释放的原因,可以右健 Path to GC Roots-->exclue all phantom/weak/soft etc. reference :

得到的结果是:

从表中可以看出 PreferenceManager -> … ->HomePage这条线路就引用着这个 HomePage实例。用这个方法可以快速找到某个对象的 GC Root,一个存在 GC Root的对象是不会被 GC回收掉的

关于Histogram 的对比请参见:http://blog.csdn.net/lang_man_xing/article/details/22160849

使用Mat分析大堆信息的更多相关文章

  1. 在Eclipse中使用MAT分析Android程序内存使用状况(转)

    对于Android这种手持设备来说,通常不会带有太大的内存,而且一般用户都是长时间不重启手机,所以编写程序的时候必须要非常小心的使用内存,尽量避免有内存泄露的问题出现.通常分析程序中潜在内存泄露的问题 ...

  2. 使用Memory Analyzer tool(MAT)分析内存泄漏(二)

    转载自:http://www.blogjava.net/rosen/archive/2010/06/13/323522.html 前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那 ...

  3. 使用Memory Analyzer tool(MAT)分析内存泄漏

    前言的前言 写blog就是好,在大前提下可以想说什么写什么,不像投稿那么字字斟酌.上周末回了趟成都办事,所以本文来迟了.K117从达州经由达成线往成都方向走的时候,发现铁路边有条河,尽管我现在也不知道 ...

  4. 老李案例分享:MAT分析应用程序服务出现内存溢出过程

    老李案例分享:MAT分析应用程序服务出现内存溢出过程   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的loa ...

  5. 【转】如何使用MAT分析内存泄漏

    原文链接:http://www.lightskystreet.com/2015/09/01/mat_usage/ MAT - Memory Analyzer Tool 使用进阶 Sep 1, 2015 ...

  6. 使用MAT分析内存泄露

    使用MAT分析内存泄露 对于大型服务端应用程序来说,有些内存泄露问题很难在测试阶段发现,此时就需要分析JVM Heap Dump文件来找出问题.随着单机内存越来越大,应用heap也开得越来越大,动辄十 ...

  7. 性能监控 | MAT分析内存泄漏

    使用MAT分析内存泄漏(二)八周年重印版 - 知乎 .u-safeAreaInset-top { height: constant(safe-area-inset-top) !important; h ...

  8. JVM探秘:MAT分析内存溢出

    本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. MAT是分析Java堆内存的一个工具,全称是 The Eclipse Memory A ...

  9. 013 - 关于GC root: Native Stack | MAT分析

      Question:   I have some third library code that I run and after some time I run into OutOfMemoryEr ...

随机推荐

  1. Spring Object/XML mapping example

    In this tutorial, we will extend last Maven + Spring hello world example by adding JDBC support, to ...

  2. Android流量监控 思路,想法

    1,开启一个服务,每5分钟跑动一次更新流量,用于能够准确记录流量         每一个小时,更新一次流量,用于清除非本月的流量 2,保存流量的时候,进行判断         a,若是数据库中保存的 ...

  3. linux的shell脚本入门

    Linux shell脚本入门教程 为什么要进行shell编程 在Linux系统中,虽然有各种各样的图形化接口工具,但是sell仍然是一个非常灵活 的工具.Shell不仅仅是命令的收集,而且是一门非常 ...

  4. OGNL stack value 值栈(主要参考官方手册)

    The framework uses a standard naming context to evaluate OGNL expressions. The top level object deal ...

  5. 【Java】IO技术的使用——用IO实现大文件的复制

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827481.html 用IO进行文件复制,实质就是用FileInputStream链接要复制的文件,按一定规模 ...

  6. MsSQL的游标的综合运用

    USE [ChiefWMS]GO/****** Object: StoredProcedure [dbo].[WMS_Check] Script Date: 04/05/2016 09:51:13 * ...

  7. 在Oracle数据库启动时提示没有权限 ora-01031:insufficient privileges

    环境:Linux 操作语句: [oracle@ora11r2 ~]$ sqlplus /nolog SQL*Plus: Release 11.1.0.6.0 - Production on Thu J ...

  8. mongodb 、nosql、 redis、 memcached 是什么?

    mongodb 是一个基于文档的数据库,所有数据是从磁盘上进行读写的.MongoDB善长的是对无模式JSON数据的查询.而Redis是一个基于内存的键值数据库,它由C语言实现的,与Nginx/ Nod ...

  9. Linux下升级python版本

    转载自:http://lovebeyond.iteye.com/blog/1770476 CentOS下的Python版本一般都比较低,很多应用都需要升级python来完成.我装的centOS的默认的 ...

  10. Java中字符串相等与大小比较

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...