加入收藏 | 设为首页 | 会员中心 | 我要投稿 广西网 (https://www.guangxiwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 业界 > 正文

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

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

这个时候灵光一闪突然回想起我们的tomcat的JVM配置参数里面好像有一个是忽略代码里面调用system.gc()的配置参数。因为这个tomcat容器是被其他单位下发的已经做过优化的,所以里面有一堆的配置参数。其中被我标绿的这个-XX:DisableExplicitGC的作用就是不响应代码里面手动调用system.gc(),看下图:

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

上面我们可以看到一堆的配置,里面配置含义我们后面再讲。这个时候我以为我已经找到了问题的本质,由于direct Memory在堆外,所以对young gen 的gc过程中是不会回收的。JVM只会在old gen GC(full GC/major GC或者concurrent GC都算)的时候才会对old gen中的对象做reference processing,而在young GC时只会对young gen里的对象做reference processing。也就是说,做full GC的话会对old gen做reference processing,进而能触发Cleaner对已死的DirectByteBuffer对象做清理工作。而如果很长一段时间里没做过GC或者只做了young GC的话则不会在old gen触发Cleaner的工作,那么就可能让本来已经死了的、但已经晋升到old gen的DirectByteBuffer关联的direct Memory得不到及时释放,这么分析看来这里就是问题的根本了。。。

那我们直接把那个参数删掉不就好了吗,我想了想自己的代码里面也没写过system.gc所以应该影响不大,然后就果断去掉了那个参数顺手也设置了个直接内存大小,配置参数是-XX:MaxDirectMemorySize。这个直接内存不设置时,默认大小是最大堆大小,看下图源码。

这么修改完之后又开始做压力测试,这次看到内存很稳定,测试二十多个小时,内存基本增长到两个多G就没再涨了,心情相当开心。然后我再去检查GC日志发现果然出现了很多system.gc的日志,这个之前都是没见过的,看下图:

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

本以为这次分析到这就结束了,可是没想到后面还有新发现,把我本以为下了定论的答案又推翻了。。。有点自己打自己脸的感觉‍♂️

Part5.Tomca配置和调优

在分析GC日志的时候,我看到压力测试中GC日志中Full gc的次数有点频繁,而且这种Full gc是Stop-the-world的,很影响应用的响应时间,从GC日志中可以看到基本一次Full GC耗时要一秒多,频率高的话很影响性能。然后我又开始搜资料,搜资料的过程中发现Tomcat8默认用NIO是指在linux服务器下,而我是在Windows的服务器上跑的。。。然后我发现Tomcat支持三种接收请求的模式,分别是:BIO,NIO,APR,其中NIO就是我们上面提到的在linux服务器上默认的模式。网上有人对这三种模式分别作了性能测试,发现APR模式是三种模式里面性能最好的,这种方式是从操作系统级别解决异步IO问题,也是Tomcat运行高并发应用的首选。但是开启比较麻烦,需要一些额外的jar包,有兴趣的也可以自行查资料了解一下。我上面也提到了我这里用的Tomcat是经过优化的,然后我打开server.xml看了一眼,结果两眼一黑,我用的Tomcat疑似采用的就是APR这种模式,因为我看到Server.xml中包含这么一句配置:

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

(编辑:广西网)

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