加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长资讯 > 外闻 > 正文

值得阅读的内存泄露分析总结和Tomcat调优

发布时间:2019-03-02 14:31:08 所属栏目:外闻 来源:今日头条
导读:副标题#e# 写在最前面,运行环境:tomcat8,jdk1.8,windows server 2008内存16G,软件LoadRunner11,MAT和JProfile9.1。 问题描述:前段时间遇到一个很奇怪的问题,开发的WEB应用,经常会毫无症状的宕掉,然后抓了线程栈看下,发现之前写的数据库链接池出

MAT是专门用来分析内存dump文件的工具,需要有Eclipse才能跑。先用jmap指令可以抓到dump文件,具体指令格式如下:

  1. jmap-dump:format=b,file=output pid 

pid就是你的java进程id,需要注意的是使用这个方法抓dump时,tomcat要用startup.bat去启动,如果以服务的方式启动,这个指令会报错,可能是权限问题。这里有个要注意的,抓Heap dump时会先进行垃圾回收,再生成dump文件。

直接用MAT打开Dump文件,然后工具还会帮你生成一份分析报告,告诉你可能存在内存泄露的地方。废话不多说,上图,下图是对内存泄露的分析报告,点进去可以看到详情信息

MAT最重要的功能就是可以分析Heap里的Object、类和引用关系。

下图列出了Heap中所有的对象,这里是以Class的方式展示的,然后这里末尾两列需要关注一下,Shallow Heap是自身在Heap里面占用的大小,Retained Heap是引用的对象总工占用的大小,单位都是字节。因为一开始就是怀疑代码存在内存泄露,担心代码里面定义的静态变量占用内存太多。刚开始看到String类型占用了大部分堆内存,然后进去可以看到String类里面由哪些对象引用占用了。

下图是查看String类的所有引用对象,然后点最后一个Retained Heap可以按从大到小排列,可以看到,最大的那几个果然是我自己代码里面定义的静态变量,图中圈红的地方就是类的堆栈地址,因为这个静态缓存的类是单例实现的,所以在这里出现这个类名的地方后面跟的堆栈地址都是一样的。

MAT还支持查询,根据类名,查询某个地址上的对象,下图就是通过地址查找某个对象。

通过一些分析我发现之前担心静态变量太多导致内存占用太多其实是多虑了,因为缓存的那几个静态变量都只存了一份,并且他们的Retained Heap也不大,对整个内存没多大影响。虽然对内存泄露分析没什么进展但是还是有一些发现,我看到了很多在代码中手动调用logger.info()打印的日志信息都存在堆中。这些logger.info当初都是为了调试或者分析问题时添加的,后面也就放着没删,有一些打印输出的内容还挺大,这些后面都会占用Heap。

MAT还有个很重要的骚操作就是可以添加两个Dump来对比,现在回想我觉得这个其实就可以确定是否存在内存泄露。抓Dump时要注意的是抓两个Dump中间最好要有一定的时间间隔,这个时间间隔中最好应用要经过一定的压力测试。下图就是两个Dump的对比图,第二个Dump就是我用LoadRunner压了一晚上之后再抓的。这里#0就是第二个Dump,#1就是第一个Dump。可以发现,一个晚上的压力测试之后,在GC之后生成的Heap Dump文件里面Shallow Heap的大小变化不是很大,Object的数量变化也不是很大,说明了GC对Heap里面对象回收状况差不多,如果存在内存泄露,存在不能被回收的对象,那第二个Dump文件里面应该会出现比第一个Dump文件大很多的类和Object,可是经过这么长时间的压力测试,并没有出现这种扎眼球的对象和类,所以基本可以断定应用不存在内存泄露的状况。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读