是什么导致 JVM 进行主要的垃圾回收?

2024-01-19

我有一个 Java 应用程序,它在不同的环境中显示不同的 GC 行为。在一种环境中,仅当堆已满 > 90% 时,堆使用情况图才会呈缓慢锯齿状,每 10 小时左右就会发生一次主要 GC。在另一个环境中,JVM 每小时准时执行一次主要 GC(此时堆通常在 10% 到 30% 之间)。

我的问题是,是什么因素导致JVM决定进行Major GC?

显然,它在堆接近满时收集,但还有一些其他原因在起作用,我猜测与我的应用程序中每小时计划的任务有关(尽管此时内存使用量没有峰值)。

我认为 GC 行为在很大程度上取决于 JVM;我在用:

  • Java HotSpot(TM) 64 位服务器 VM 1.7.0_21 Oracle Corporation
  • 没有特定的 GC 选项,因此使用 64 位服务器的默认设置(PS MarkSweep 和 PS Scavenge)

其他信息:

  • 这是一个在 Tomcat 6 中运行的 Web 应用程序。
  • 在这两种环境中,永久代都徘徊在 10% 左右。
  • 具有锯齿行为的环境具有 7Gb 最大堆,其他环境具有 14Gb。

请不要猜测。 JVM 必须具有决定何时执行主要 GC 的规则,并且这些规则必须在源代码深处的某个位置进行编码。如果有人知道它们是什么,或者记录在哪里,请分享!


我发现了四种可能导致主要 GC 的情况(给定我的 JVM 配置):

  1. old gen区已满(即使可以增长,仍然会先运行一次major GC)
  2. Perm gen 区域已满(即使可以增长,仍然会先运行一次Major GC)
  3. 有人手动呼叫System.gc():一个坏库或与 RMI 相关的东西(参见链接1 http://alexandru-ersenie.com/2011/01/11/j2ee-full-garbage-collections-when-running-with-cms-garbage-collection-strategy/, 2 http://fedora.fiz-karlsruhe.de/docs/Wiki.jsp?page=Java+Heap+%26+GC+Tuning and 3 https://www.java.net/node/690169)
  4. 年轻一代区域已满,没有任何东西可以移入老一代(请参阅1 http://alexandru-ersenie.com/2011/01/11/j2ee-full-garbage-collections-when-running-with-cms-garbage-collection-strategy/)

正如其他人评论的那样,情况 1 和 2 可以通过分配大量堆和永久代并设置来改进-Xms and -Xmx为相同的值(以及等效的 Perm)以避免动态堆大小调整。

可以使用以下方法避免情况 3-XX:+DisableExplicitGC flag.

情况 4 需要更多的调整,例如,-XX:NewRatio=N (see Oracle 的调优指南 http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是什么导致 JVM 进行主要的垃圾回收? 的相关文章

随机推荐