如何在Linux JVM 64位上发生OutOfMemoryError

在我的unit testing中,我故意尝试引发OutOfMemoryErrorexception。 我使用如下的简单语句:

byte[] block = new byte[128 * 1024 * 1024 * 1024]; 

该代码适用于Win7 64位,带有jdk6u21 64位。 但是当我使用jdk6u21在Centos 5 64bit上运行时,没有抛出OutOfMemoryError,即使我使数组的大小更大。

任何想法?

如果您只想消耗所有内存,请执行以下操作:

  try { List tempList = new ArrayList(); while (true) { tempList.add(new byte[128 * 1024 * 1024 * 1024]); } } catch (OutOfMemoryError OME) { // OK, Garbage Collector will have run now... } 

Linux并不总是会立即为您分配所需的所有内存,因为许多真正的应用程序需要的内容超出了他们的需求。 这被称为overcommit(这也意味着它有时会猜错,而可怕的OOM杀手罢工)。

对于你的unittest,我只是手动抛出OutOfMemoryError 。

128 * 1024 * 1024 * 1024 = 0,因为int是32位。 Java不支持大于4Gb的arrays。

 ulimit -v 102400 ulimit -d 102400 unitTest.sh 

以上应将您的unit testing限制为1M的虚拟内存和1M数据段大小。 当您到达其中任何一个时,您的流程应该获得ENOMEM。 小心,这些限制适用于您调用它们的进程/ shell; 你可能想在子shell中运行它们。

man 2 setrlimit有关如何在引擎盖下工作的详细信息。 help ulimit获取ulimit命令。

您可以使用-Xmx标志故意将JVM的最大堆大小设置为少量。

启动以下程序:

 public final class Test { public static void main(final String[] args) { final byte[] block = new byte[Integer.MAX_VALUE]; } } 

使用以下JVM参数: -Xmx8m

这样就可以了:

 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at Test.main(Test.java:4) 

小点,但分配新的long [Integer.MAX_VALUE]会使内存速度提高8倍。 (每个约16 GB)

没有OutofMemoryError的原因是内存正在以未提交状态分配,没有页面。

如果在arrays的每个4K中写入一个非零字节,那么将导致分配内存。