java - 终身 Collection 无明显原因启动

标签 java garbage-collection

我有一个 Java 应用程序,通常具有非常健康的垃圾收集统计信息。永久收集通常每小时左右发生一次,而 STW 部分只需要几分之一秒。但奇怪的是,收集总是在应用程序启动后的前五分钟内发生。这是一个真正的问题,因为那时,CPU 使用率已经比正常情况高得多(由于最终被缓存的网络调用增加),因此这些暂停总是比正常情况要长,如果我正在执行以下操作,甚至会运行超过 8 秒在极重负载下重新启动。

以下是 JVM 参数:

-Xms4096m 
-Xmx4096m 
-XX:PermSize=768m 
-XX:MaxPermSize=768m 
-XX:SurvivorRatio=6 
-XX:NewSize=1024m 
-verbose:gc 
-XX:-DisableExplicitGC 
-XX:+PrintGCDetails 
-XX:+PrintGCApplicationStoppedTime 
-XX:+PrintGCTimeStamps 
-XX:+PrintHeapAtGC 
-XX:+PrintTenuringDistribution 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:MaxDirectMemorySize=2048m 
-XX:+UseConcMarkSweepGC 
-XX:+CMSClassUnloadingEnabled 
-XX:+PrintConcurrentLocks 
-XX:+ExplicitGCInvokesConcurrent 

这里的问题是,是什么触发了这个永久收集,因为当它发生时,旧一代中几乎有 2GB 空闲空间。以下是正常情况下在永久收集之前的用法:

concurrent mark-sweep generation total 3145728K, used 2897098K 

下面是启动后几分钟内触发永久收集之前的用法:

concurrent mark-sweep generation total 3145728K, used 1573655K 

我的理解是,只有当老一代几乎满时,才会发生终身收集;否则什么会触发它?

最佳答案

CMS 的一个关键概念是,它应该在空间耗尽之前开始收集,从而允许它同时运行。如果它等到你用完,就会触发串行停止世界收集。

因此,有两个阈值来确定何时提前触发收集。

-XX:CMSInitiatingOccupancyFraction=90 (by default)
-XX+UseCMSInitiatingOccupancyOnly

如果您不设置这些,那么什么时候是开始使用“指标”的好时机

My understanding is that a tenured collection should only occur when old gen is nearly full;

这就是并行收集器的作用。

关于java - 终身 Collection 无明显原因启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26107171/

相关文章:

java - 如何正确关闭MySql数据库连接

java - 如何在触发器的帮助下更新不同 sql 表中的行

java - Java 垃圾收集器导致性能低下?需要建议

java - 针对少量和长时间 GC 运行的 JVM 调优

Java 在释放对象和垃圾回收后仍然使用系统内存

java - Spring 安全@PreAuthorize ("hasAnyRole(' ... .')")

java - 当值发生变化时,面板上的组件如何向面板外的其他组件发出警报?

c# - 从 ascx 页面中的 C# 方法调用返回的字符串的垃圾收集

c# - 我如何明确清除字节 []

java - 为什么这个简单的 Java 字节码会导致 StackOverflow 错误?