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