G1 垃圾收集器:烫发生成无限期填满,直到执行完整的 GC
我们有一个相当大的应用程序运行在JBoss 7应用程序服务器上。过去,我们使用ParallelGC,但它在某些服务器中给我们带来了麻烦,其中堆很大(5 GB或更多),并且通常几乎填满,我们会经常得到很长的GC暂停。
最近,我们对应用程序的内存使用进行了改进,并在少数情况下为运行该应用程序的一些服务器添加了更多RAM,但我们也开始切换到G1,希望减少这些暂停的频率和/或更短。事情似乎有所改善,但我们看到了一个以前从未发生过的奇怪行为(使用ParallelGC):Perm Gen似乎很快就会填满,一旦它达到最大值,就会触发Full GC,这通常会导致应用程序线程长时间暂停(在某些情况下,超过1分钟)。
几个月来,我们一直在使用512 MB的最大烫发大小,在我们的分析过程中,使用ParallelGC,烫发大小通常会停止在390 MB左右增长。然而,在我们切换到G1之后,上述行为开始发生。我尝试将最大烫发大小增加到1 GB甚至1,5 GB,但仍然会发生完整的GC(它们只是不那么频繁)。
在此链接中,您可以看到我们正在使用的分析工具(YourKit Java Profiler)的一些屏幕截图。请注意,当触发完整GC时,伊甸园和旧世代有很多可用空间,但烫发大小处于最大值。在完整GC之后,Perm大小和加载类的数量急剧减少,但它们再次开始上升并且循环重复。代码缓存很好,永远不会超过38 MB(在本例中为35 MB)。
下面是 GC 日志的一段:
2013-11-28T11:15:57.774-0300: 64445.415: [全GC 2126M->670M(5120M), 23.6325510 秒] [伊甸园: 4096.0K(234.0M)->0.0B(256.0M) 幸存者: 22.0M->0.0B 堆: 2126.1M(5120.0M)->670.6M(5120.0M)] [倍数: user=10.16 sys=0.59, real=23.64 秒]
您可以在此处查看完整日志(从我们启动服务器的那一刻起,到完整GC后的几分钟)。
以下是一些环境信息:
java 版本 “1.7.0_45”
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64 位服务器虚拟机(内部版本 24.45-b08,混合模式)
启动选项:-Xms5g -Xmx5g -Xss256k -XX:PermSize=1500M -XX:MaxPermSize=1500M -XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintAdaptiveSizePolicy -Xloggc:gc.log
所以这是我的问题:
这是G1的预期行为吗?我在网上发现了另一个帖子,有人质疑非常相似的东西,并说G1应该在Perm Gen上执行增量收集,但没有答案......
在我们的启动参数中,有什么我可以改进/纠正的吗?服务器有8 GB的RAM,但似乎我们并不缺乏硬件,在触发完整的GC之前,应用程序的性能很好,这时用户会遇到很大的滞后并开始抱怨。