java - 过于激进的垃圾收集支配着 CPU

标签 java server configuration garbage-collection cpu-usage

我已经回顾了与我的标题相似的其他问题,但它们似乎都没有涵盖与我正在经历的情况非常相似的情况。我的应用程序正常启动,以常规和预期的方式进行垃圾收集。

2018-05-21T20:08:41.136-0400: 19979.368: [GC (Allocation Failure) [PSYoungGen: 71364K->10997K(73728K)] 303964K->243661K(466944K), 0.0165899 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
2018-05-21T20:09:01.212-0400: 19999.444: [GC (Allocation Failure) [PSYoungGen: 71413K->11065K(73728K)] 304077K->243865K(466944K), 0.0121248 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
2018-05-21T20:09:30.450-0400: 20028.682: [GC (Allocation Failure) [PSYoungGen: 71481K->12550K(73728K)] 304281K->245422K(466944K), 0.0133476 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
2018-05-21T20:09:50.492-0400: 20048.723: [GC (Allocation Failure) [PSYoungGen: 72966K->10454K(73728K)] 305838K->243374K(466944K), 0.0141533 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 

在看似任意的时间后,垃圾收集变得非常激进,每秒运行几次并消耗 CPU 的整个运行时间。它会保持此状态,直到应用程序重新启动。

2018-05-21T20:10:12.104-0400: 20070.335: [GC (Allocation Failure) [PSYoungGen: 70870K->10356K(73728K)] 303790K->243340K(466944K), 0.0193899 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
2018-05-21T20:10:12.222-0400: 20070.453: [GC (Allocation Failure) [PSYoungGen: 70772K->2080K(72704K)] 303756K->235288K(465920K), 0.0090667 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
2018-05-21T20:10:12.413-0400: 20070.645: [GC (Allocation Failure) [PSYoungGen: 61472K->1936K(73728K)] 294680K->235256K(466944K), 0.0081242 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
2018-05-21T20:10:12.519-0400: 20070.751: [GC (Allocation Failure) [PSYoungGen: 61328K->1585K(81408K)] 294648K->235248K(474624K), 0.0053709 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
2018-05-21T20:10:12.582-0400: 20070.813: [GC (Allocation Failure) [PSYoungGen: 67633K->1313K(82432K)] 301296K->235240K(475648K), 0.0080559 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
2018-05-21T20:10:12.647-0400: 20070.878: [GC (Allocation Failure) [PSYoungGen: 67361K->1121K(92160K)] 301288K->235264K(485376K), 0.0052482 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] 
2018-05-21T20:10:12.718-0400: 20070.950: [GC (Allocation Failure) [PSYoungGen: 76897K->801K(92672K)] 311040K->235256K(485888K), 0.0071820 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
2018-05-21T20:10:12.792-0400: 20071.024: [GC (Allocation Failure) [PSYoungGen: 76577K->641K(105472K)] 311032K->235232K(498688K), 0.0070387 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
2018-05-21T20:10:12.878-0400: 20071.109: [GC (Allocation Failure) [PSYoungGen: 89217K->32K(105472K)] 323808K->235249K(498688K), 0.0084592 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
2018-05-21T20:10:12.962-0400: 20071.194: [GC (Allocation Failure) [PSYoungGen: 88608K->64K(119296K)] 323825K->235289K(512512K), 0.0066050 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

当 CPU 如此占用时,我的应用程序无法正常工作。服务器有两个 CPU,但 JVM 似乎只使用其中一个,pidstat 报告的平均使用率刚刚超过 100%。

这种行为最让我困惑的是,年轻一代被压低到分配给它的空间的一小部分并保持在那里,在垃圾收集后永远不会超过 1 Mb。

我怎样才能防止这种情况发生,或者我能做些什么来诊断这种情况发生的原因?我不是调整垃圾回收方面的专家,所以我可以使用一些经验丰富的指导。

我当前的 JVM 配置是:

-XX:InitialHeapSize=268435456 
-XX:MaxHeapSize=2147483648 
-XX:+PrintGC 
-XX:+PrintGCDateStamps 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-XX:+UseCompressedClassPointers 
-XX:+UseCompressedOops 
-XX:+UseParallelGC 

最佳答案

您正在描述垃圾回收“死亡螺旋”的症状。

基本上,如果您有一个堆,其中可到达对象占用的空间呈持续上升趋势,并且越来越多的时间花在运行垃圾收集器上。最终,堆将完全填满,或者 GC 开销限制将被突破。在任何一种情况下都会抛出 OOME。

基本上有三种方法:

  1. 定期重启应用程序。
  2. 增加堆大小。
  3. 找出您的应用程序使用越来越多堆空间的原因。通常存在某种存储泄漏。

只有第 3 种方法真正解决了问题,其他方法都是“创可贴”解决方案。


While the CPU is thus engaged, my application doesn't work properly. The server has two CPUs, but the JVM only appears to use one of them, with pidstat reporting average usage of just over 100%.

如果 GC 承受的压力太大(例如,由于“几乎已满”的堆),那么您可能会发现它必须退回到非人体工程学的操作模式。例如,它可能已决定在 JVM 启动时只创建一个后台 GC 线程,这在正常情况下没问题,但在极端 GC 负载下该线程将达到 100%,然后您的应用程序线程将被阻塞。

基本上,当堆太小而无法满足应用程序的需求时,GC 无法正常工作。

关于java - 过于激进的垃圾收集支配着 CPU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50470193/

相关文章:

java - 无法在plugins {} block 中使用 'jsonschema2pojo' gradle插件?

linux - AWS EC2 - 服务器程序的 "bill by hour"有什么问题?

java - 您如何在 OSGi 中正确地将 ManagedServiceFactory 实现为声明式服务?

java - 如何测试 EntityManager.persist() 调用

java - 无法让 HTTP Post 工作

java - 无法转换为 [Ljava.lang.Object;

基于 python 的 https 服务器在提供响应后关闭连接

java - 如何在 Apache Tomcat 中找到管理控制台?

java - Grails日志配置正在劫持外部日志配置,如何阻止它?

java - JList 变为空白 [我认为输出流缓冲问题]