JVM在未指定Xmx参数的情况下尝试分配超过128M Xms时出现错误。

3

我运行应用程序时遇到了JVM问题,只需使用以下Java命令:

C:\Users\optitest>I:\j2sdk\bin\java -version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)

C:\Users\optitest>I:\j2sdk\bin\java -Xms4g -version
Error occurred during initialization of VM
Incompatible minimum and maximum heap sizes specified

即使将Xms设置为128M也无效:
C:\Users\optitest>I:\j2sdk\bin\java -Xms128m -version
Error occurred during initialization of VM
Incompatible minimum and maximum heap sizes specified

仅当Xms设置为64M或更低时才起作用:

C:\Users\optitest>I:\j2sdk\bin\java -Xms64m -version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)

有趣的是,如果我指定Xmx,它就能正常工作。
C:\Users\optitest>I:\j2sdk\bin\java -Xms4g -Xmx4g-version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)

C:\Users\optitest>I:\j2sdk\bin\java -Xms4g -Xmx8g-version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01, mixed mode)

更有趣的事情是:所有以上命令在另一台具有相同操作系统(Windows Server 2008 R2 Enterprise SP1)和相同jdk版本的机器上正常运行。物理内存为16GB。
有任何想法吗?
3个回答

1

有什么想法吗?

显而易见的结论是,如果您想使用-Xms指定初始堆大小,并且您希望将大小设置为大于默认最大堆大小的值,则需要指定最大堆大小。

您在不同的计算机上获得不同结果的原因是JVM根据Java版本和执行平台以不同的方式计算默认堆大小。在某些情况下,它是一个常数。在其他情况下,它取决于系统上的物理内存量。

只需明确设置最大堆大小,您就不会遇到这个问题。


如果您想找出特定计算机的默认堆大小,请运行以下命令:
java -XX:+PrintFlagsFinal -version 

谢谢,Stephen。问题出在“麻烦”的机器上,它是一个64位操作系统,有16GB的物理内存。我个人认为设置Xms128m不应该有任何问题,因为显然默认的Xmx不应该小于128M。 - Xiaofeng
只是为了澄清:无论是“故障”机器还是“无故障”机器都在运行64位Windows Server 2008 R2 Enterprise 64位操作系统,拥有16GB物理内存。 - Xiaofeng
显然它“存在问题”...无论你是否认为它应该存在问题。如果你对我的解释不满意,我建议你通过Java支持合同向Oracle提问...或者下载OpenJDK 6源代码并尝试自己弄清楚实际发生了什么。告诉我们你认为“不应该发生”是...嗯...无意义的,因为它显然确实发生了。 - Stephen C
1
嗯,请不要误解我的意思。你的评论真的很有帮助,我只是好奇为什么两台机器的工作方式不同。好消息是:我使用了更新的JDK版本(1.6_u17不支持此选项)来运行带有-XX:+PrintFlagsFinal命令的程序,结果让我感到惊讶。 "有问题"的机器显示“uintx MaxHeapSize := 0 {product}”,而“好”的机器显示“uintx MaxHeapSize := 4160749568 {product}”。现在看起来有点棘手...为什么有问题的机器的MaxHeapSize为零? - Xiaofeng
我猜,也许有一些操作系统设置(访问控制?安全性?)防止JVM找出“故障”机器上有多少物理内存。 - Stephen C
注意大数字和PrintFlagsFinal,如果大于4094m,则无法正确显示它们,因为它将它们显示为uint,因此限制为4,294,967,295。 $ java -Xmx4g -XX:+PrintFlagsFinal -version | grep "MaxHeapSize" uintx MaxHeapSize := 0 {product} - cmcginty

0

我也遇到了同样的问题。我正在进行调试,但似乎这可能与默认的MaxHeapSize有关,它被设置为TOTALRAM/4或(16GB/4 = 4GB = 2^32):

(uint32) 2^32 = 0

我从-XX:PrintFlagsFinal得到了以下输出:
uintx MaxHeapSize                              := 0               {product}

而且-XX:+PrintCommandLineFlags的输出确认了4G值:

-XX:InitialHeapSize=268428160 -XX:MaxHeapSize=4294850560 -XX:+PrintCommandLineFlags -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC

0

你的机器堆大小取决于比你拥有多少RAM更多的因素!

32位或64位JVM的最大堆大小看起来很容易确定,只需查看可寻址内存空间,如32位JVM的2^32(4GB)和64位JVM的2^64。

你不能真正将4GB设置为32位JVM的最大堆大小,使用-Xmx JVM堆选项。你会得到“无法创建Java虚拟机,无效的最大堆大小:-Xmx”错误。

你可以在这里找到一个关于堆大小的详细解释文档。

另一个重要的事情是,你只能通过增加堆大小来推迟OutofMemory异常。除非你清理内存,否则你迟早会遇到这个异常使用像Visual VM这样的应用程序来了解后台发生了什么。我建议你尝试优化代码,以提高性能。


谢谢,Dileep。正如我对Stephen的评论所述,"麻烦"和"无麻烦"机器都是Windows Server 2008 R2 Enterprise 64位,带有16GB物理内存。只是好奇为什么设置Xms128m不起作用,因为默认分配的Xmx应该明确大于16GB物理内存上的128m。 - Xiaofeng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接