我试过像这样增加堆内存:
-Xmx9g -Xms8g
老实说,只是因为我可以。
现在我想知道,为什么 JVM 不使用更多它,并且不那么频繁地安排 GC。
系统:
JVM:Java HotSpot(TM) 64 位服务器 VM(24.51-b03,混合模式)
Java:版本1.7.0_51,供应商Oracle Corporation
编辑:
我想改进我的建模过程配置(吞吐量胜过响应速度)。
最佳答案
Java 1.7 中的 HotSpot JVM separates the heap into a few spaces ,与本次讨论相关的是:
- 伊甸园,新事物的归宿
- Survivor,在 Eden 被 GC 后,如果需要的话,对象会去哪里
当您分配一个新对象时,它只是简单地附加到 Eden 空间中。一旦伊甸园满了,它就会在所谓的“小集合”中被清理干净。 Eden 中仍可访问的对象被复制到 Survivor,然后 Eden 被删除(从而收集所有未被复制的对象)。
您想要填满 Eden,而不是整个堆。
例如,以这个简单的应用为例:
public class Heaps {
public static void main(String[] args) {
Object probe = new Object();
for (;;) {
Object o = new Object();
if (o.hashCode() == probe.hashCode()) {
System.out.print(".");
}
}
}
}
probe
的作用就是确保 JVM 无法优化掉循环;重复的 new Object()
正是我们所追求的。如果您使用默认的 JVM 选项运行它,您将得到一个与您看到的一样的图表。对象分配在 Eden 上,这只是整个堆的一小部分。一旦 Eden 满了,它就会触发一次小收集,清除所有这些新对象并将堆使用率降低到其“基线”,接近于 0。
那么,如何填满整个堆?把伊甸园设得很大! Oracle 发布其 heap tuning parameters ,这里相关的两个是 -XX:NewSize
和 -XX:MaxNewSize
。当我使用 -Xms9g -XX:NewSize=8g -XX:MaxNewSize=8g
运行上述程序时,我得到的结果更接近您的预期。
在一次运行中,这几乎用完了所有堆,以及我指定的所有 Eden 空间;随后的运行只占用了我指定的 Eden 的一小部分,如您在此处所见。我不太清楚这是为什么。
VisualVM 有一个名为 Visual GC 的插件,可让您查看有关堆的更多详细信息。这是我的屏幕截图,在正确的时刻拍摄,显示 Eden 几乎已满,而旧空间几乎是空的(因为循环中的那些 new Object()
都没有在 Eden 集合中存活下来).
关于java - 为什么 JVM 不使用更多的堆内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24137280/