【发布时间】:2021-03-19 18:30:08
【问题描述】:
我想获得在 Java 中创建最大可能数组所需的确切内存量。
我的测试程序:
public class MemoryOfArraysTest {
public static void main(String... args) {
Object[] array = new Object[Integer.MAX_VALUE - 2];
}
}
我通过自己的测试知道数组的最大长度是Integer.MAX_VALUE - 2 (2147483645)。
如果数字更大,您将收到以下错误:
Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at MemoryOfArraysTest.main(MemoryOfArraysTest.java:3)
但这只是接近数组最大长度的一步。另一个问题是您的 VM 可以使用的内存。您可以使用-Xmx 指定内存。
如果我使用java -Xmx1g MemoryOfArraysTest(只有 1GB 内存)运行我的课程,我会收到预期错误:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at MemoryOfArraysTest.main(MemoryOfArraysTest.java:3)
如果我使用java -Xmx10g MemoryOfArraysTest(10GB 内存)运行它,它就可以工作。
这是我目前所拥有的。但是我的程序需要的确切内存量是多少?最好在 KB 中。有没有办法计算?
【问题讨论】:
-
这是一个非常酷的概念,但是为什么?
-
Integer.MAX_VALUE - 2 == 数组中的 2147483646 个元素。在具有
-XX:+UseCompressedOops(默认值)的 64 位 VM 上,引用占用 4 个字节。目前 OpenJDK 上的数组头占用 16 个字节(stackoverflow.com/questions/17335884/…,注意 Zing 和 OpenJ9 可以不同,项目 Lilliput 最终会出现),所以 2147483646 * 4 + 16 个字节。但为什么?这很少需要知道。你在解决什么问题,你想达到什么目标? -
实际上不可能找出来。或者至少,这是不可行的。您无法知道类加载器加载的其他类占用了多少堆空间(例如所有 java.lang 废话)。在不知道这一点的情况下,您无法知道还剩下多少堆空间。默认情况下加载的东西所使用的确切堆数量在几乎每个 JDK 构建之间都会略有不同。
-
旁注:可能的最大数组是
long[]或double[],因为每个条目将占用64位或8字节。使用最大可能的数组大小 (Integer.MAX_VALUE = 2^31 - 1) 进行计算会产生略高于16GB (17179869192字节) 的大小 -
当然它没有真正的用例。我不是想创建一个这样长度的数组。我真的很想知道一个方程是什么以及在 Java 中一般如何管理数组。但我认为这样问不会得到回答。因为我的问题不会很清楚。感谢所有提供答案的cmets。它们帮助我更多地理解记忆的主题。