java – 过度积极的垃圾收集主宰CPU

我已经回顾了与我有类似头衔的其他问题,但是它们似乎都没有涵盖我所经历的情况.我的应用程序正常启动,以常规和预期的方式收集垃圾.

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 Overhead Limit将被破坏.无论哪种情况,都会抛出OOME.

基本上有三种方法:

>定期重启应用程序.
>增加堆大小.
>弄清楚您的应用程序使用越来越多的堆空间的原因.通常存在某种存储泄漏.

只有第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的设计不能很好地工作.

相关文章

摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠...
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠...
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个...
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:...
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程...