使用Mat分析大堆信息

在定位一线问题时经常碰测试中出现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消息的内容解决了我的问题。

时间: 2024-11-17 20:20:59

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

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

对于Android这种手持设备来说,通常不会带有太大的内存,而且一般用户都是长时间不重启手机,所以编写程序的时候必须要非常小心的使用内存,尽量避免有内存泄露的问题出现.通常分析程序中潜在内存泄露的问题是一件很有难度的工作,一般都是由团队中的资深工程师负责,而且随着程序代码量的提高,难度还会逐步加大. 今天要介绍一个在Eclipse中使用的内存分析工具——MAT(Eclipse Memory Analyzer,主页在http://www.eclipse.org/mat/).它是一个功能非常丰富的J

nginx源码分析--配置信息的继承&amp;合并

这里只讲述http{}模块下的配置: 在ngx_http_block()函数内(这个函数别调用时在ngx_inti_cycle内的ngx_conf_parse函数,这个函数遇到http命令时 回调ngx_http_block,开启http{}配置块的解读工作),针对每一个http模块,调用init_conf之后,有调用了ngx_http_merge_servers().这是为何! 首先明确几点:一个http{}配置块内可以包含多个server{}配置块,每个server{}配置块可以包含多个lo

使用MAT分析Java内存

Overview MAT(Memory Analyzer Tool) 是一个JAVA Heaper分析器,可以用来分析内存泄露和减少内存消耗.分析Process showmap中的/dev/ashmem/dalvik-heap(deleted)一项所占用的Memory.可以参考我写的使用showmap分析系统内存占用情况一文. 下面就将一下如何使用Eclipse MAT分析Android应用程序内存的消耗.所需要的是已经安装ADT和SDK的Eclipse.然后可以在http://www.ecli

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

Question: I have some third library code that I run and after some time I run into OutOfMemoryError. So I fired up the Eclipse MAT and analyzed the memory. Now it seems the memory can't be disposed because there is an object that is a shown as GC roo

jstat的使用/jam的使用/使用MAT分析内存溢出/

2.通过jmap监控内存使用情况 2.1 监控堆内存   jamp -heap 12840 2.2 监控内存中对象的数量及其大小 查看所有对象的数量以及大小包括类型:jmap -histo 14116 | more 查看所有对象的数量以及大小包括类型:jmap -histo:live 14116 | more 2.3 通过jmap导出堆内存使用情况的文件 2.4  通过jhat查看dump文件并且进行分析,启动一个HTTP端口进行访问,通过该端口可以查看到整个应用程序所使用的的所有对象的情况,提

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

前言 在平时工作过程中,有时会遇到OutOfMemoryError,我们知道遇到Error一般表明程序存在着严重问题,可能是灾难性的.所以找出是什么原因造成OutOfMemoryError非常重要.现在向大家引荐Eclipse Memory Analyzer tool(MAT),来化解我们遇到的难题.如未说明,本文均使用Java 5.0 on Windows XP SP3环境. 为什么用 MAT 之前的观点,我认为使用实时profiling/monitoring之类的工具,用一种非常实时的方式来

eclipse MAT分析heap dump

官方参考文档:http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Ftasks%2Fanalyzingthreads.html 代码 /** * -XX:+PrintGC -Xloggc:gc.log * * VM args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError */ public class HeapOOM { static class OO

用MAT分析JAVA程序运行时的内存使用情况

Java出现OutOfMemoryError或者发现Java应用程序占用的内存很异常,那么我们一般采用下面的步骤分析:A. 把Java应用程序使用的heap dump下来B. 使用Java heap分析工具,找出内存占用超出预期的嫌疑对象C. 根据情况,分析嫌疑对象和其他对象的引用关系.D. 分析程序的源代码,找出嫌疑对象数量过多的原因.以下面的代码为例: public class TObject { int[] arr = new int[20000]; } public class Test

Android 性能优化之使用MAT分析内存泄露问题

我们平常在开发Android应用程序的时候,稍有不慎就有可能产生OOM,虽然JAVA有垃圾回收机,但也不能杜绝内存泄露,内存溢出等问题,随着科技的进步,移动设备的内存也越来越大了,但由于Android设备的参差不齐,可能运行在这台设备好好的,运行在那台设备就报OOM,这些适配问题也是比较蛋疼的,比如我们平常运行着一个应用程序,运行的好好的,突然到某个Activity就给你爆出一个OOM的错误,你可能会以为是这个Activity导致的内存泄露,你会想到也有可能是内存有泄露吗?内存泄露就像一个定时炸