使用eclipse MAT分析内存状态

背景

        前段时间,生产环境服务器出现了OOM,并没有什么吃内存的功能,服务器分配的内存余量还是很大的,为什么会这样呢?程序出现OOM,自然是程序中申请内存没有释放也就是通常所说的内存泄漏,或者申请的内存超出了JVM能提供的内存大小,此时称之为内存溢出。那么如何查看占用内存多的地方在哪里呢?

-XX:+HeapDumpOnOutOfMemoryError

        线上环境运行JVM进程时,建议加上此参数,目的是在JVM发生OOM时自动生成内存快照。

Eclipse Memory Analyzer

使用eclipse MAT分析内存状态_第1张图片
dump出来的内存,加载进去之后是这个样子

        1、从MAT的分析报告中我们看出,org.apache.tomcat.util.threads.TaskThread @ 0x6e5a26f40 http-nio-8080-exec-39 这个线程持有的本地变量多达3.9GB。

        2、通过List object with outgoing 可以看到是哪个reference占用了如此多的内存。

使用eclipse MAT分析内存状态_第2张图片
对象list

        这个图中可以看出一个com.mysql.jdbc.ByteArrayRow的数组几乎占满了 3.9GB的空间,推断应该是某个sql查询判断条件没有加号,查出了太多的记录,还未来得及转化成对应的object就已经OOM了。利用thread_overview可以看到是哪个接口导致了这个情况。

thread_overview 页

        通过thread_overview页,可以查看发生OOM时此线程的调用堆栈。

使用eclipse MAT分析内存状态_第3张图片
调用堆栈

    一个很深的调用堆栈,找到程序中的代码片段,就定位到了具体的方法。

使用eclipse MAT分析内存状态_第4张图片
定位到程序中出问题的方法

        展开方法名,是可以看到调用参数的。最后定位到问题,是程序中新加的方法传了一个空字符串作为参数,在判断中漏掉了,最终把满足所有条件的数据查了出来,导致OOM。

        到此为止,已经找出原因,最终系统及时修复并上线。搞定OOM的三板斧大概就是这样,非常简单,但很实用。

你可能感兴趣的:(使用eclipse MAT分析内存状态)