JVM的FullGC优化实战(一)

今天我们的城市站项目(city-web)在早上9点钟出现了多次FullGC,导致网站报警严重。如下图示

JVM的FullGC优化实战(一)_第1张图片

    从上图可以看到,FullGC非常频繁,一分钟之内达到20多次,这种情况下几乎等于程序宕机,因为在FullGC的时候,几乎无法对外提供服务。通过监控视图也证明了这一点:

    从上图可见,我们的项目是6台集群,“假死”了四台,都是因为FullGC的原因,当然“假死”一会儿后,也会随着FullGC的结束再次“活”过来。

JVM的FullGC优化实战(一)_第2张图片

    同时,老年代对象表现的非常糟糕,GC以后,立马再涨上来。说明程序中对老年代对象的对象的控制出现了问题。

于是我们让运维dump了当时的内存city.hprof,用eclipse的Memory Analyzer Tool打开分析内存,分析结果是:

JVM的FullGC优化实战(一)_第3张图片

    接着点击Leak Suspects链接,查询具体的内存分析报表:

JVM的FullGC优化实战(一)_第4张图片

上图看到,有80%的内存被StandardManager对象占用了。而内存被一个ConcurrentHashMap的实例堆积而来。建议查询的关键字是下面三个:

org.apache.catalina.loader.StandardClassLoader @ 0x77805f3c0
org.apache.catalina.session.StandardManager
java.util.concurrent.ConcurrentHashMap$Segment[]

然后点Details链接:

JVM的FullGC优化实战(一)_第5张图片

    查看源码(apache-tomcat-7.0.67-src.zip)得知,在StandardManager的父类中,确实存在一个老年代的对象,是用ConcurrentHashMap来存储的,如下:

/**
     * The set of currently active Sessions for this Manager, keyed by
     * session identifier.
     */
    protected Map sessions = new ConcurrentHashMap();

 

主流互联网会话管理机制都是cookies+cache,那么代码里哪里会用到Session呢?查看代码暂时没有发现,这里有一篇文章:一次由于垃圾session分配造成的内存惨案。其中讲到,由于Session创建过多,造成了session的大量堆积,导致内存泄露。目前线上环境的session的超时时间依然是30分钟,按照上面文章中介绍的办法,把session的超时时间设置为3分钟。

随后观察,FullGC依然会有,但不像原来那么频繁了。

JVM的FullGC优化实战(一)_第6张图片

同样,老年代对象依旧在涨:

JVM的FullGC优化实战(一)_第7张图片

 

根本问题还没有解决,笔者将继续观察该问题。解决方案查看:JVM的FullGC优化实战(二)

参考链接:

http://blog.csdn.net/kobejayandy/article/details/8496663

http://www.51testing.com/html/78/23978-212519.html

http://blog.csdn.net/rachel_luo/article/details/8992461

你可能感兴趣的:(java,线上故障)