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

前端之家收集整理的这篇文章主要介绍了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的设计不能很好地工作.

原文链接:/java/437494.html

猜你在找的Java相关文章