值得阅读的内存泄露分析总结和Tomcat调优
这个看名字就知道是用来检测是否存在内存泄露的,后面看到Tomcat管理页面自带一个Find Leaks的功能,不知道是不是和这个有关系。然后我进这个类看了下就有了新发现,在这个类里面我看到GC日志里面执行system.gc的那个类名!看下图: 这里这个gcDaemonProtection的参数在这个类的上面已经定义了,默认是true。这就意味着如果不手动修改配置文件,肯定会进这个判断。里面用反射调用了sun.misc.GC的requestLatency方法。我点进这个sun.misc.GC类里面,看到了GC日志里面那个run的地方,看下图: 看名字这是一个守护进程,里面调用了system.gc(),这下可以肯定的是GC日志里频繁出现的Full GC操作就是这里引起的(后面我又抓了很多次线程栈发现调用GC的只有这一个类)。到这里我终于可以确定为什么GC日志里面那么多Full GC了,都是因为Tomcat配置里面加载这个内存检测的Class导致的。那有什么办法可以避免这个呢,后来网上查了下,有这么几种方法: ① 直接去掉这个配置 ② 将上面那个默认配置true的参数改成false,将Server.xml里面的对应那条配置中增加下面的一段:
③ 增加-XX:+ExplicitGCInvokesConcurrent配置,这个参数不会像DisableExplicitGC一样强行忽略手动调用system.gc,而是在遇到调用system.gc时调用CMS垃圾回收方法。因为上面提过CMS是停顿最短的GC方法,这样就可以避免由full GC带来的长GC pause引起的性能问题。 经过测试我是采用的第三个方法,到最后内存增长的问题得到了解决。最后我们看一下GC日志中CMS的耗时,看下图: 这里被我用红线划得就是mark和remark的两个阶段,因为这有这两个阶段是Stop-the-world的,可以看到耗时和Full GC比起来要短很多。 最后Tomcat的JVM配置参数被我修改为下图: 这里面有几个比较重要好用的我大概说一下: -Xloggc:gc.log -XX:+PrintGCDetails,这个参数会设置打印GC日志,这次问题,靠GC日志分析出了很多有用的东西。 -XX:+UseConcMarkSweepGC ,选用CMS作为垃圾回收方法 -XX:+ ExplicitGCInvokesConcurrent,用这个替换了DisableExplicitGC,每次遇到system.gc时调用一次CMS回收,并不是直接Stop-the-world。 -XX:+UseCMSCompactAtFullCollection,在每次CMS收集器在完成垃圾回收之后做一次内存碎片整理。 Tomcat的线程池也是可以自己配置的,包括可接受的连接数之类的,这里我就不展开说了,码字也不轻松… 其他还有很多有兴趣的可以自行了解。 总结 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |