为什么JVM总是以FULL GC开始?

4

我正在对运行在JBoss AS5上的Web应用程序进行调优基准测试。

我使用JMeter创建不同的场景,从低负载开始到压力负载。

我注意到GC日志总是以一次完整的GC开始。

有人能解释一下这个行为吗?

提前感谢。

顺便说一下,这是GC日志的一部分:

17.560: [Full GC [PSYoungGen: 44456K->0K(458752K)] [ParOldGen: 0K->4385K(1572864K)]      44456K->4385K(2031616K) [PSPermGen: 11565K->11555K(262144K)], 0.9226691 secs]
72.478: [GC [PSYoungGen: 393216K->30720K(458752K)] 397601K->35105K(2031616K), 0.1787110    secs]
112.137: [GC [PSYoungGen: 423936K->38912K(458752K)] 428321K->43297K(2031616K), 0.2197971 secs]
188.297: [GC [PSYoungGen: 432128K->54272K(458752K)] 436513K->58657K(2031616K), 0.3034273 secs]
309.100: [GC [PSYoungGen: 447488K->60416K(458752K)] 451873K->64801K(2031616K), 0.3111470 secs]
430.354: [GC [PSYoungGen: 453632K->65536K(454848K)] 458017K->72129K(2027712K), 0.3374716 secs]
546.078: [GC [PSYoungGen: 454848K->65536K(415104K)] 461441K->78881K(1987968K), 0.3746511 secs]
652.116: [GC [PSYoungGen: 415104K->40960K(436928K)] 428449K->88641K(2009792K), 0.3895185 secs]
765.134: [GC [PSYoungGen: 390528K->28672K(437632K)] 438209K->94882K(2010496K), 0.2703870 secs]
870.726: [GC [PSYoungGen: 380800K->23552K(375680K)] 447010K->102114K(1948544K), 0.1948568 secs]
976.144: [GC [PSYoungGen: 375680K->18432K(436096K)] 454242K->110306K(2008960K), 0.1734677 secs]
2个回答

2

并不是所有程序都以GC(垃圾回收)开始,你可以有一个从未进行GC的程序。

然而,当JVM启动时,默认使用最小量的内存。

应用程序正在构建数据结构,并且高比例的对象将被保留。这不是正常行为,幸存者空间可能会耗尽。JVM被调整为假定大多数新创建的对象将被丢弃。当幸存者空间耗尽时,将触发Full GC。

由于您知道应用程序将增长到多少内存,因此可以使用像

-ms512m -mx1g

完全垃圾收集将会消失,你需要更少的收集次数。

+Peter 感谢您的回答。这些选项设置为以下-Xms2g -Xmx2g。 - M.ES
在这种情况下,我也会尝试设置新的大小 -XX:NewSize=1g。通常我会从8 GB的新应用程序大小开始,并从那里逐渐减小。 ;) - Peter Lawrey
+Peter 再次感谢。但是你如何将年轻代的大小设置为大于堆8GB? - M.ES
我使用-XX:NewSize=8g -mx12g或类似的参数。现在可能出现的问题是什么呢?仔细阅读第一行,我可以看到初始perm gen已经填满了。PSPermGen: 11565K->11555K这在我使用JSE加载远少于代码的应用程序中从未发生过。我不确定如何设置初始perm gen大小,但您可以增加最大值,这可能会增加最小值。 - Peter Lawrey
我发现 FullGC 在应用程序部署之前发生!它发生在启动 JBoss 服务器时?有什么帮助吗? - M.ES
显示剩余4条评论

0

在 Jboss 社区的 Peter Johnson 的帮助下,我已经知道了这个问题的答案。

我在这里写下来与大家分享。

对 System.gc() 的调用被编码到应用服务器中(或者编码到它使用的库之一——我知道 RMI 库喜欢进行 GC 调用),我怀疑是在从引导程序转换到应用服务器本身时。我认为在部署或其他重要的初始化活动之后,它可能还会执行另外一个或两个 GC。我认为这背后的想法是在处理用户请求之前尽可能使堆清除垃圾。当然,那是多年前的事情,当服务器没有那么多内存而堆更小的时候是有意义的。我在 JBoss AS 4.0.x 到 5.x 的版本中看到过这种行为(没有监视 6 上的 GC 行为)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接