Java ConcurrentMarkSweep 垃圾收集器未发生

标签 java garbage-collection concurrent-mark-sweep

环境详细信息: 操作系统:Linux 红帽 Java:JRE 6 更新 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

通过此设置,应用程序开始时会出现一次 Full 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 决定关闭,那么我预计它将恢复使用经典的“吞吐量”GC 算法。而且很有可能它会等到堆满,然后运行完整的 GC。简而言之,如果你让它继续下去,那就没问题了(模数你会时不时地遇到大的 GC 暂停。)

<小时/>

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

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

相关文章:

java - 通过 Searchable xml 配置设置 Android 搜索小部件选项

Android:平板电脑Honey comb中出现内存不足异常

c# - 为什么 GC 在我引用它时收集我的对象?

java - 可以增加引用旧对象的 gc 时间短命对象吗?

java - 我应该如何针对我的应用程序调整 CMS?

Java ConcurrentMarkSweep 垃圾收集器不清除所有垃圾

java - jdk中String类的indexOf方法是使用BF实现的,为什么不使用KMP或BM呢?

java - Rhino、typeof 和自动装箱混淆

java - 如何检测java中JFrame内的按钮被单击

python - 当定义函数但未调用函数时,Python 解释器会解析变量引用吗?