java - 是什么导致 JVM 进行主要的垃圾收集?

标签 java garbage-collection jvm jvm-hotspot

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

我的问题是,导致 JVM 决定执行主要 GC 的因素是什么?

很明显,它会在堆快满时进行收集,但还有其他原因在起作用,我猜这与我的应用程序中的每小时计划任务有关(尽管此时内存使用量没有峰值)。

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

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

其他信息:

  • 这是一个在 Tomcat 6 中运行的网络应用程序。
  • Perm gen 在两种环境中都徘徊在 10% 左右。
  • 具有锯齿行为的环境有 7Gb 最大堆,另一个有 14Gb。

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

最佳答案

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

  1. old gen area已经满了(即使可以增长,还是会先跑一个major GC)
  2. perm gen区满了(即使可以增长,还是会先跑一个major GC)
  3. 有人手动调用 System.gc():一个错误的库或与 RMI 相关的东西(参见链接 123)
  4. 年轻一代区域都已满,没有任何东西可以移动到老一代(参见 1)

正如其他人评论的那样,可以通过分配大量堆和 permgen 并将 -Xms-Xmx 设置为相同的值(以及使用 perm 等效项)以避免动态调整堆大小。

可以使用 -XX:+DisableExplicitGC 标志避免情况 3。

案例 4 需要更多的调整,例如,-XX:NewRatio=N(参见 Oracle's tuning guide)。

关于java - 是什么导致 JVM 进行主要的垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22249869/

相关文章:

VB.Net Office 互操作 - Excel 进程未关闭

java - 哪些 Java 代码会强制 javac 1.6 使用 'swap' 和 'nop' 操作码?

java - 使用 SWT 解决 NoClassDefFoundError 异常

java - 我应该如何在 RxJava 中建模流程?

java -/usr/bin/time 是否包括 java 程序的程序后垃圾收集?

java - 为数据密集型应用程序的 JVM 提供适当的堆和旧代大小

java - 调试和正常执行模式之间的不同行为 - WeakReference 处理

java - 如何调用一个方法,直到它每 x 分钟返回 true

java - JavaFX中Event consumes的含义是什么

java - 为什么在使用 G1 GC 时推荐使用 Java 10?