一次使用 Eclipse Memory Analyzer 分析 Tomcat 内存溢出
2015-02-13 17:23
453 查看
最近,线上生产系统突然频繁的 JVM 内存报警!但本系统近期内并没有上线改动!为了能查清内存报警的原因,使用 Eclipse Memory Analyzer tool(MAT)对 JVM Dump 文件进行了分析!1. 生成 dump 文件用 jmap 生产 dump 文件
通过 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 里包含了多了很多详细的异常描述信息,之前是没有的。
排查下游系统代码,发现在返回异常时,与之前异常抛出有所不同:
当没有 message,message = cause.toString(),所以就造成了返回大量不必要的异常信息,从而影响了上游系统!参考:http://tivan.iteye.com/blog/1487855
—————————— 本文同步发布于 ZHANGSR 我的个人博客 ——————————
jmap -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
—————————— 本文同步发布于 ZHANGSR 我的个人博客 ——————————
相关文章推荐
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析weblogic内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出(转)
- 使用 Eclipse Memory Analyzer 进行内存泄漏分析的一次过程
- 使用Eclipse Memory Analyzer对Tomcat进行内存分析
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- [置顶]使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 一次使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 使用Eclipse Memory Analyzer进行内存泄漏分析三部曲
- 使用Eclipse Memory Analyzer分析Tomcat内存溢出
- 《JVM故障诊断指南》之5 —— HPROF :使用Eclipse Memory Analyzer 工具 (MAT)进行内存泄露分析