java没有正确保留巨大的初始堆大小

时间:2014-05-25 21:59:18

标签: java memory-management heap-memory gentoo

我正在使用512GB RAM(由多个AMD Opteron 6212 CPU处理)的单台机器上工作。目前大约有300GB RAM免费。通过运行

运行大型Java计算
java path/to/myApp -Xms280g -Xmx280g > output.txt

应该使Java立即保留280GB,如果失败则会出错。奇怪的是,没有发生错误,但top仅显示30.4GB的内存使用量,但它不会崩溃。怎么会发生这种情况?如果无法分配初始堆大小,是不是java应该崩溃?

实际上,一旦30.4GB已满,我就会在达到280GB之前获得OutOfMemory / Java堆空间/ GC开销限制错误。使用250GB或300GB运行会产生类似的30.3GB~30.4GB限制。我在Gentoo Linux上运行带有OpenJDK运行时环境(IcedTea6)的OpenJDK 64位服务器虚拟机,并且有足够的可用内存(超过300GB)。

4 个答案:

答案 0 :(得分:14)

参数的顺序不正确。您将-Xms280g -Xmx280g作为参数传递给您自己的程序而不是JVM。正确的是:

java -Xms280g -Xmx280g path/to/myApp

答案 1 :(得分:2)

如果您希望在应用程序初始化期间抓取-Xms中指定的内存,请使用

java -XX:+ AlwaysPreTouch -Xms2G -Xmx2G ......

AlwaysPreTouch将在JVM初始化期间要求每个内存页面,而不是仅仅将不需要的内容保存为“虚拟”。但请注意,这在JVM启动时会有一些延迟。

使用上述开关,然后用顶部检查。您的JVM将获得完整的2G(实际上更多)。

答案 2 :(得分:0)

尝试在cmdline中添加-d64参数

java -d64 path/to/myApp -Xms280g -Xmx280g > output.txt

答案 3 :(得分:0)

所以你达到了大约32 GB的限制。虽然Oracle谈论Compressed oops in the Hotspot JVM,但它也说约32GB。

但是,在LP64系统上,任何给定运行的堆可能必须大约是相应ILP32系统的1.5倍(假设运行适合两种模式)。这是由于托管指针的扩展大小。内存非常便宜,但是现在带宽和缓存供不应求,所以只是为了超过4Gb限制而大大增加堆的大小是痛苦的。

(另外,在x86芯片上,ILP32模式提供了LP64模式的一半可用寄存器.SPARC不会受到这种影响; RISC芯片从大量寄存器开始,只是为LP64模式加宽它们。)

压缩的oops表示托管指针(在JVM中的许多但不是所有位置)作为32位值,必须按8倍缩放并添加到64位基址以查找它们引用的对象。这允许应用程序处理多达40亿个对象(而不是字节),or a heap size of up to about 32Gb.

Link here