环境详细信息:
操作系统:Linux RedHat
Java:JRE 6 Update 21

我正在为我的应用程序使用以下GC设置。

-server -d64 -Xms8192m -Xmx8192m -javaagent:lib/instrum.jar -XX\:MaxPermSize=256m -XX\:+UseParNewGC -X\:+ParallelRefProcEnabled -XX\:+UseConcMarkSweepGC -XX\:MaxGCPauseMillis=250 -XX\:+CMSIncrementalMode -XX\:+CMSIncrementalPacing -XX\:+CMSParallelRemarkEnabled -verbose\:gc -Xloggc\:/tmp/my-gc.log -XX\:DisableExplicitGC -XX\:+PrintGCTimeStamps -XX\:+PrintGCDetails -XX\:+UseCompressedOops


有了该设置,在应用程序开始时只有一个完整GC

2.946: [Full GC 2.946: [CMS: 0K->7394K(8111744K), 0.1364080 secs] 38550K->7394K(8360960K), [CMS Perm : 21247K->21216K(21248K)], 0.1365530 secs] [Times: user=0.10 sys=0.04, real=0.14 secs]


其次是4-5成功的CMS收集,但是此后在日志中没有CMS的痕迹,只有次要收集中有条目。

379022.293: [GC 379022.293: [ParNew: 228000K->4959K(249216K), 0.0152000 secs] 7067945K->6845720K(8360960K) icms_dc=0 , 0.0153940 secs]


堆持续增长,已达到7GB。由于无法承受OOM或生产系统中的任何故障,我们必须重新启动应用程序。

我无法理解CMS收集器为何停止清洁。欢迎任何提示/建议。提前致谢。

================================================== ===================================
1月23日更新。

谢谢大家到目前为止的回答。我已经在测试环境中设置了应用程序,并使用以下一组JVM选项测试了该应用程序:

选项1

-server -d64 -Xms8192m -Xmx8192m -javaagent\:instrum.jar -XX\:MaxPermSize\=256m -XX\:+UseParNewGC -XX\:+UseConcMarkSweepGC -verbose\:gc -Xloggc\:my-gc.log -XX\:+PrintGCTimeStamps -XX\:+PrintGCDetails


选项#2

-server -d64 -Xms8192m -Xmx8192m -javaagent\:instrum.jar -XX\:MaxPermSize\=256m -XX\:+UseParNewGC -XX\:+UseConcMarkSweepGC -verbose\:gc -Xloggc\:my-gc.log -XX\:+DisableExplicitGC -XX\:+PrintGCTimeStamps -XX\:+PrintGCDetails


我同时使用这两种设置进行了2天的测试。这些是我的观察:

选项1
堆内存稳定,但是有90个ConcurrentMarkSweep集合,JVM花了24分钟。太高了而且我在GC日志中看到以下几行,并且模式每隔一小时就会继续...

318995.941: [GC 318995.941: [ParNew: 230230K->8627K(249216K), 0.0107540 secs] 5687617K->5466913K(8360960K), 0.0109030 secs] [Times: user=0.11 sys=0.00, real=0.01 secs]
319050.363: [GC 319050.363: [ParNew: 230195K->9076K(249216K), 0.0118420 secs] 5688481K->5468316K(8360960K), 0.0120470 secs] [Times: user=0.12 sys=0.01, real=0.01 secs]
319134.118: [GC 319134.118: [ParNew: 230644K->8503K(249216K), 0.0105910 secs] 5689884K->5468704K(8360960K), 0.0107430 secs] [Times: user=0.11 sys=0.00, real=0.01 secs]
319159.250: [Full GC (System) 319159.250: [CMS: 5460200K->5412132K(8111744K), 19.1981050 secs] 5497326K->5412132K(8360960K), [CMS Perm : 72243K->72239K(120136K)], 19.1983210 secs] [Times: user=19.14 sys=0.06, real=19.19 secs]


我没有看到并发的标记和清除日志。这是否意味着CMS已切换到吞吐量收集器?如果可以,为什么?

选项2:

由于我看到了Full GC(系统)日志,因此我想到添加-XX \:+ DisableExplicitGC。但是使用该选项,收集不会发生,并且当前堆大小为7.5G。我想知道的是,为什么CMS执行Full GC而不是并发收集。

最佳答案

这是一个理论...

我怀疑那些CMS收集并不完全成功。 12477.056处的事件似乎是CMS可能已决定,由于“预清理”步骤花费的时间太长,CMS无法正常工作。

如果那导致CMS决定关闭电源,那么我希望它将恢复为使用经典的“吞吐量” GC算法。而且很有可能它会等到堆满后再运行完整的GC。简而言之,如果您让它继续下去就可以了(取模,您会时不时地得到大的GC暂停。)



建议您在具有相同堆大小和其他GC参数的测试服务器上运行应用程序,并查看服务器达到限制时会发生什么。它实际上会引发OOME吗?

关于java - Java ConcurrentMarkSweep垃圾收集器未发生,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8798184/

10-14 12:16