GC时间非常长

时间:2012-12-12 02:17:18

标签: java garbage-collection jvm-arguments

我们使用以下启动参数运行JBoss,但是在GC时间长(> 5分钟)时遇到问题。

-Xms116042m -Xmx116042m -XX:PermSize=256M -XX:MaxPermSize=256M -XX:+UseConcMarkSweepGC -verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -XX:MaxHeapFreeRatio=95 

关于如何最大限度地缩短GC时间的任何建议?

注意:这些是16个四核CPU,128GB linux机器。

GC日志:

我在GC日志中看到很多"CMSbailing out to foreground collection"条消息:

130904.206: [GC 130904.206: [ParNew: 240819K->25522K(249216K), 0.2391170 secs] 80798776K->80588205K(118799360K), 0.2395380 secs] [Times: user=2.56 sys=0.01, real=0.24 secs] 
130904.799: [GC 130904.799: [ParNew: 247018K->27648K(249216K), 0.2071170 secs] 80809700K->80601600K(118799360K), 0.2075260 secs] [Times: user=2.61 sys=0.00, real=0.21 secs] 
130905.455: [GC 130905.455: [ParNew: 249216K->27648K(249216K), 0.2808950 secs] 80823168K->80644147K(118799360K), 0.2813140 secs] [Times: user=2.66 sys=0.00, real=0.28 secs] 
130905.765: [Full GC (System) 130905.765: [**CMSbailing out to foreground collection**
131167.602: [CMS-concurrent-mark: 284.753/303.276 secs] [Times: user=909.49 sys=193.05, real=303.23 secs] 
 (concurrent mode interrupted): 80616499K->74658646K(118550144K), 554.7507700 secs] 80651365K->74658646K(118799360K), [CMS Perm : 112620K->112582K(262144K)], 554.7511550 secs] [Times: user=784.15 sys=175.10, real=554.65 secs] 
131461.127: [GC 131461.128: [ParNew: 221568K->27648K(249216K), 0.2620780 secs] 74880214K->74691531K(118799360K), 0.2624960 secs] [Times: user=2.28 sys=0.00, real=0.27 secs] 
131461.698: [GC 131461.699: [ParNew: 249216K->27647K(249216K), 0.3827130 secs] 74913099K->74807895K(118799360K), 0.3829550 secs] [Times: user=3.52 sys=0.41, real=0.39 secs] 
131462.754: [GC 131462.754: [ParNew: 249215K->27648K(249216K), 0.3022410 secs] 75029463K->74827673K(118799360K), 0.3026050 secs] [Times: user=2.36 sys=0.02, real=0.30 secs] 
131463.789: [GC 131463.790: [ParNew: 249216K->22291K(249216K), 0.2396390 secs] 75049241K->74841234K(118799360K), 0.2400980 secs] [Times: user=2.38 sys=0.06, real=0.24 secs] 

5 个答案:

答案 0 :(得分:1)

无论是使用conc mark还是并行gc,扫描116 Gb的垃圾都会花费很多时间。我总是发现this document是调整GC最有用的信息来源。 GC调整将根据您的应用需求而定,并且没有通用解决方案,但有许多选项可用。

你可能会对G1GC有更多的好运,因为它将堆分成许多小部分并独立扫描它们,但它仍然可能容易受到随机的OOME的影响。

如果调整GC无法产生足够的响应时间,请将机器拆分为多个16到32 Gb RAM的虚拟机并对其进行聚类。如果它是一个EJB应用程序,并且你正确地烘焙了你的bean,它可能不像看起来那么痛苦。

答案 1 :(得分:0)

我观察到完整GC发生的一个原因是因为你的年轻一代比需要的更早填满,需要将对象复制到老一代。所以我们可以尝试以下选项

  1. 为您的年轻一代设置初始大小,如下所示  -XX:NewSize = 500m -XX:MaxNewSize = 500m

  2. 您可以将年轻一代的口粮设定为老一代的因素  -XX:NewRatio = 3

  3. 希望这会有所帮助......

答案 2 :(得分:0)

您可以将初始堆设置为较小的值。通过这样做,启动时间将减少。因为java不想在启动时分配一个非常大的堆。这将为GC节省一些时间,因为它通常会运行相对较小的堆。

答案 3 :(得分:0)

由于您看到“并发模式中断”消息,并且在GC时似乎您的世代都没有填满,我认为有一个明确的System.gc()调用导致您的完整GC。尝试添加JVM参数-XX:+ ExplicitGCInvokesConcurrent以使System.gc()调用调用CMS。此外,如果您自己致电System.gc(),请确定原因并尽可能删除。

答案 4 :(得分:0)

将Java堆大小设置得如此接近物理可用内存并不是一个好主意,除了使用-Xmx配置之外,总是会有一些开销。如果你有很多线程,那么堆栈将需要很多。你看过输出了吗? “vmstat 1”看看它是否在交换?