相关疑难解决方法(0)

Tomcat内存越来越大

导致tomcat内存增长和下降的原因

java apache tomcat

11
推荐指数
1
解决办法
814
查看次数

Java ConcurrentMarkSweep垃圾收集器不会删除所有垃圾

简短形式:CMS垃圾收集器似乎未能收集到越来越多的垃圾; 最终,我们的JVM填满了,应用程序变得没有响应.通过外部工具(JConsole或jmap -histo:live)强制GC 清除它一次.

更新:问题似乎与JConsole的JTop插件有关; 如果我们不运行JConsole,或者在没有JTop插件的情况下运行它,行为就会消失.

(技术说明:我们在Linux 2.6.9盒子上运行Sun JDK 1.6.0_07,32位.升级JDK版本并不是一个选择,除非有一个不可避免的主要原因.另外,我们的系统不是连接到可访问Internet的计算机,因此JConsole等的屏幕截图不是一个选项.)

我们当前正在运行带有以下标志的JVM:

-server -Xms3072m -Xmx3072m -XX:NewSize=512m -XX:MaxNewSize=512m 
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled 
-XX:CMSInitiatingOccupancyFraction=70 
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 
-XX:+DisableExplicitGC
Run Code Online (Sandbox Code Playgroud)

在JConsole中观察内存图,有一个完整的GC,在我们的应用程序生命周期的前几个小时内每隔约15分钟运行一次; 在每个完整的GC之后,仍然有越来越多的内存在使用中.几个小时后,系统达到稳定状态,CMS旧版中大约有2GB的已用内存.

这听起来像是经典的内存泄漏,除非我们使用强制完整GC的任何工具(点击JConsole中的"收集垃圾"按钮,或运行jmap -histo:live等),旧版本突然降至~500MB使用,我们的应用程序在接下来的几个小时内再次响应(在此期间相同的模式继续 - 在每个完整的GC之后,越来越多的旧版本已经满了.)

需要注意的一点是:在JConsole中,报告的ConcurrentMarkSweep GC计数将保持为0,直到我们使用jconsole/jmap/etc强制GC.

使用jmap -histo并按jmap -histo:live顺序,我能够确定明显未收集的对象包括:

  • 几百万HashMaps和阵列HashMap$Entry(以1:1的比例)
  • 数百万Vectors和Object数组(1:1的比例,与HashMaps的数量大致相同)
  • 数百万HashSet,Hashtablecom.sun.jmx.remote.util.OrderClassLoaders,以及数组Hashtable$Entry(大约相同数量;大约是HashMaps和Vectors的一半)

下面的GC输出中有一些摘录; 我对它们的解释似乎是CMS GC中止而没有故障转移到世界各地的GC.我是否以某种方式误解了这个输出?有什么东西会导致这种情况吗?

在正常运行时期间,CMS GC输出块看起来像这样:

36301.827: [GC [1 CMS-initial-mark: 1856321K(2621330K)] 1879456K(3093312K), 1.7634200 secs] [Times: user=0.17 sys=0.00, real=0.18 secs]
36303.638: [CMS-concurrent-mark-start] …
Run Code Online (Sandbox Code Playgroud)

java garbage-collection concurrent-mark-sweep

10
推荐指数
2
解决办法
9628
查看次数