意外的内存不足分配大于堆的数组时出错
我今天正在玩OOM错误,我发现了一些我无法解释自己的东西。
我尝试分配一个大于堆的数组,期望出现“请求的数组大小超过 VM 限制”错误,但收到“Java 堆空间”错误。
根据 JDK 11 文档“3 解决内存泄漏>了解内存不足错误异常”:
线程thread_name中的异常:java.lang.OutOfMemoryError: 请求的数组大小超过 VM 限制
原因:详细消息“请求的数组大小超过 VM 限制”指示应用程序(或该应用程序使用的 API)试图分配大于堆大小的数组。例如,如果应用程序尝试分配 512 MB 的数组,但最大堆大小为 256 MB,则将引发 OutOfMemoryError,理由是“请求的数组大小超过 VM 限制”。
法典:
public class MemOverflow {
public static void main(final String[] args) {
System.out.println("Heap max size: " + (Runtime.getRuntime().maxMemory() / 1024 / 1024) + "MB");
long[] array = new long[100_000_000]; // ~800MB
System.out.println(array.length);
}
}
此代码按预期工作,堆足够大以存储我的数组:
$ javac MemOverflow.java && java -Xmx800m MemOverflow
Heap max size: 800MB
100000000
但是,当我减小堆大小时,我得到错误的OOM错误:
$ javac MemOverflow.java && java -Xmx100m MemOverflow
Heap max size: 100MB
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at MemOverflow.main(MemOverflow.java:5)
# I'm expected the "Requested array size exceeds VM limit" error here
我在这里错过了什么吗?我知道我可以生成我想要用作数组大小的错误,但我希望通过调整堆大小来抛出它。Integer.MAX_VALUE
Java 版本 :
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu120.04)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu120.04, mixed mode)
编辑:根据@cdalxndr答案,我也尝试了Oracle最新的JDK 15,但我得到了相同的结果。
java version "15" 2020-09-15
Java(TM) SE Runtime Environment (build 15+36-1562)
Java HotSpot(TM) 64-Bit Server VM (build 15+36-1562, mixed mode, sharing)
编辑 2:我报告了:JDK-8254804。
编辑3:2021-01-19更新
文档已修复。在 v16-ea(抢先体验)中。
线程thread_name中的异常:java.lang.OutOfMemoryError: 请求的数组大小超过 VM 限制
原因:详细信息消息“请求的数组大小超过 VM 限制”指示应用程序(或该应用程序使用的 API)试图分配大小大于 JVM 实现限制的数组,而不管有多少堆大小可用。
编辑4:2021-03-20更新