继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

使用 Eclipse Memory Analyzer 分析 Tomcat 内存溢出

守着星空守着你
关注TA
已关注
手记 351
粉丝 39
获赞 267

最近,线上生产系统突然频繁的 JVM 内存报警!但本系统近期内并没有上线改动!

为了能查清内存报警的原因,使用 Eclipse Memory Analyzer tool(MAT)对 JVM Dump 文件进行了分析!

1. 生成 dump 文件

用 jmap 生产 dump 文件

map -dump:format=b,file=HeapDump.bin <pid>

2. MAT 安装与介绍

下载地址:http://www.eclipse.org/mat/downloads.php

通过 MAT 打开 dump 出来的内存文件,打开后如下图:

Histogram 可以列出内存中的对象,对象的个数以及大小。

Histogram 如下图:

Objects:类的对象的数量。
Shallow size:就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。
Retained size:是该对象自己的 shallow size,加上从该对象能直接或间接访问到对象的 shallow size 之和。换句话说,retained size 是该对象被 GC 之后所能回收到内存的总和。

我们发现 ConcurrentHashMap 类的对象占用了很多空间。

Leak Suspects 如下图:

从那个饼图,该图深色区域被怀疑有内存泄漏,可以发现整个 heap 2G 内存,深色区域就占了 98%。后面的描述,说明内存被一个实例占用了大量内存,并指出 system class loader 加载的"java.util.concurrent.concurrentHashMap$Segmen[]"实例的内存中聚集(消耗空间),并建议用关键字"java.util.concurrent.concurrentHashMap$Segmen[]"进行检查。所以,MAT 通过简单的报告就说明了问题所在。

 

Dominator Tree 如下图:>

我们逐层打开 concurrentHashMap 的内存结构,发现 Key 非常多,并且最底层的 String 长度很大!

幸运的是该系统的下游也是我们负责的系统,猜测 concurrentHashMap 应该是 RPC 调用返回回值待处理的内存存储,正常情况这个 String 的长度不很大。仔细查看, String 里包含了多了很多详细的异常描述信息,之前是没有的。

排查下游系统代码,发现在返回异常时,与之前异常抛出有所不同:

try { } catch(Exception e) {     throw e; }   ...   try { } catch(Exception e) {     throw new Exception("xxxx", e); }   // 返回伪代码 response(e.getMessage);

就是有这些许的不同,我们看下源代码:

public Throwable(String message, Throwable cause) {     fillInStackTrace();     detailMessage = message;     this.cause = cause; }   public Throwable(Throwable cause) {     fillInStackTrace();     detailMessage = (cause==null ? null : cause.toString());     this.cause = cause; }   public String getMessage() {     return detailMessage; }

当没有 message,message = cause.toString(),所以就造成了返回大量不必要的异常信息,从而影响了上游系统!

参考:

http://tivan.iteye.com/blog/1487855

原文链接:http://outofmemory.cn/java/jvm/OutOfMemoryError-with-MAT

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP