Java 数组的最大限制

maximum limit on Java array

我正尝试在 Java 中创建二维数组,如下所示:

int[][] adjecancy = new int[96295][96295];

但失败并出现以下错误:

JVMDUMP039I Processing dump event "systhrow", detail "java/lang/OutOfMemoryError" at 2017/04/07 11:58:55 - please wait.
JVMDUMP032I JVM requested System dump using 'C:\eclipse\workspaces\TryJavaProj\core.20170407.115855.7840.0001.dmp' in response to an event
JVMDUMP010I System dump written to C:\eclipse\workspaces\TryJavaProj\core.20170407.115855.7840.0001.dmp
JVMDUMP032I JVM requested Heap dump using 'C:\eclipse\workspaces\TryJavaProj\heapdump.20170407.115855.7840.0002.phd' in response to an event
JVMDUMP010I Heap dump written to C:\eclipse\workspaces\TryJavaProj\heapdump.20170407.115855.7840.0002.phd

解决此问题的方法是增加 JVM 内存,但我正在尝试提交代码以参加在线编码挑战。在那里它也失败了,我将无法在那里更改设置。

创建大型数组是否有任何不应超过的标准限制或指南?

int[][] adjecancy = new int[96295][96295];

当您这样做时,您正在尝试分配 96525*96525*32 位,这将近 37091 MB,也就是将近 37 GB。单靠 Java 从 PC 获取内存是极不可能的。

我认为您在初始化程序时不需要手头那么多数据。可能您必须查看 ArrayList,它为您提供动态大小分配,然后在运行时继续释放是一个需要考虑的关键。

创建数组没有任何限制。只要你有记忆,你就可以使用它。但请记住,您不应该持有让 JVM 生活忙碌的内存块。

这取决于您的 JVM 可用的最大内存和数组的内容类型。对于 int,我们有 4 个字节的内存。现在,如果您的机器上有 1 MB 可用内存,它最多可以容纳 1024 * 256 个整数(1 MB = 1024 * 1024 字节)。牢记这一点,您可以相应地创建二维数组。

建议分配可分配的最大堆大小为机器内存大小的1/4。

Java 中的 1 个 int 需要 4 个字节,您的数组分配需要大约 37.09GB 的内存。

在这种情况下,即使我假设您只是将完整堆分配给一个数组,您的机器也应该有大约 148GB RAM。那是巨大的。

看看下面。

参考:http://docs.oracle.com/javase/8/docs/technotes/guides/vm/gc-ergonomics.html

希望对您有所帮助。

您可以创建的数组取决于 JVM 堆大小。

96295*96295*4(每个数字的字节数)= 37,090,908,100 字节 = ~34.54 GBytes。竞争性代码评委中的大多数 JVM 都没有那么多内存。因此错误。

为了更好地了解对于给定的堆大小可以使用什么数组大小 - 运行 此代码段具有不同的 -Xmx 设置:

    Scanner scanner = new Scanner(System.in);
    while(true){
        System.out.println("Enter 2-D array of size: ");
        size = scanner.nextInt();

        int [][]numbers = new int[size][size];
        numbers = null;
    }

例如使用 -Xmx 512M -> ~10k+ 元素的二维数组。

通常大多数在线评委在评估提交时有 ~1.5-2GB 堆

数组显然必须适合内存。如果没有,典型的解决方案是:

  • 你真的需要 int(最大值 2,147,483,647)吗?也许 byte(最大值 值 127) 或 short 是否足够好? byteint 小 8 倍。
  • 数组中真的有很多相同的值(比如零)吗?尝试使用稀疏数组。

例如:

Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
map.put(27, new HashMap<Integer, Integer>()); // row 27 exists
map.get(27).put(54, 1); // row 27, column 54 has value 1.

每个存储的值需要更多内存,但对数组基本上没有限制space(您可以使用 Long 而不是 Integer 作为索引使它们变得非常大)。

  • 也许你只是不知道数组应该有多长?尝试 ArrayList,它会自动调整大小。对二维数组使用 ArrayList of ArrayLists

  • 如果没有其他方法有帮助,请使用 RandomAccessFile 将过度增长的数据存储到文件系统中。在一个好的工作站上,100 Gb 左右不是问题,您只需要计算文件中所需的偏移量。文件系统明显比RAM慢很多,但有好的SSD驱动器可能可以忍受。