【发布时间】:2014-03-07 12:16:40
【问题描述】:
我有一个 Java 应用程序,它在不同的环境中显示不同的 GC 行为。在一个环境中,堆使用图是一个缓慢的锯齿形,每 10 小时左右就会有一次主要的 GC,只有当堆 > 90% 已满时。在另一种环境中,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 应用程序。
- Perm gen 在两种环境中都徘徊在 10% 左右。
- 具有锯齿行为的环境具有 7Gb 最大堆,另一个具有 14Gb。
请不要猜测。 JVM 必须有决定何时执行主要 GC 的规则,并且这些规则必须在源代码的某个地方进行编码。如果有人知道它们是什么或记录在哪里,请分享!
【问题讨论】:
-
“在一个环境中……在另一个环境中……” 环境是什么?他们有什么不同?
-
AFAIK 可以通过提示强制 GC 执行垃圾收集,我说强制是因为我认为您不能隐式强制 GC 执行垃圾收集。
-
@CeilingGecko 你是对的,根据规范你不能强制 GC。但是,您可以很好地提出要求,也许 JVM 会遵守。通常,JVM 会在尝试实例化堆中的对象并且没有空间这样做时执行完整的 GC。至少,这是我的理解。完整 GC 还有其他触发器,谷歌搜索“什么触发完整 GC”可以找到大量信息。我相信 JVM 确定它没有空间实例化对象的具体细节由 JVM 开发人员决定。
-
嗯,不确定,但完整的旧 gen 堆不会触发完整的 gc 吗?如果您正在监视整个堆,它可能看起来大部分是空的,但老一代可能已满?
-
@chris 你有 -Xmx -r -Xms 设置吗?
标签: java garbage-collection jvm jvm-hotspot