Java数组有最大大小吗?


214

Java数组可以包含的元素数量是否有限制?如果是这样,那是什么?


5
您接受了错误的答案,只需尝试分配这么长的数组(不,我的内存不足)。
maaartinus 2012年


Answers:


184

即使测试很容易,也没有找到正确的答案。

在最新的HotSpot VM中,正确答案是Integer.MAX_VALUE - 5。一旦超出此范围:

public class Foo {
  public static void main(String[] args) {
    Object[] array = new Object[Integer.MAX_VALUE - 4];
  }
}

你得到:

Exception in thread "main" java.lang.OutOfMemoryError:
  Requested array size exceeds VM limit

57
我认为,除非我们愿意对简单明了且完全错误的答案进行否决,否则否决的想法是没有意义的。五个字节的差异实际上是否在现实世界中重要,否,当然不重要。但是令我感到担忧的是,人们愿意“权威地”给出答案,甚至不尝试看它是否真的有效。至于内存限制,DUH。就像您问我“您可以吃多少颗葡萄”?我说:“嗯,这取决于我当时冰箱里有多少冰箱。”
凯文·布瑞里恩

7
您是否偶然知道为什么它不给您这五个字节?这是否一定是Java中经常发生的事情,还是仅与计算机的内存有关?
塔蒙(Taymon)2012年

17
@Kevin Bourrillion:这似乎已经改变,使用Oracle 1.7.0_07,我最多可以分配MAX_VALUE-2元素。这与我分配的内容无关,我真的很想知道VM可以使用这两个“东西”(长度不适合2个字节)。
maaartinus 2012年

3
@TomášZato的最新时间为Integer.MAX_VALUE+1,您将有一个整数溢出。Java中的数组大小int不是long;无论您在数组,字节或引用中存储哪种数据类型。字符串只是对象引用。
已退出–Anony-Mousse 2014年

8
在JDK 6及更高版本中,数组中元素的最大数量为Integer.MAX_VALUE - 2= 2 147 483645。如果使用来运行Java,则Java将成功分配该数组-Xmx13GOutOfMemoryError: Java heap space如果通过则失败-Xmx12G
阿列克谢·伊凡诺夫

127

(当然)这完全取决于VM。

通过OpenJDK的7和8的源代码浏览java.util.ArrayList.Hashtable.AbstractCollection.PriorityQueue,和.Vector,可以看到这个要求进行重复:

/**
 * Some VMs reserve some header words in an array.
 * Attempts to allocate larger arrays may result in
 * OutOfMemoryError: Requested array size exceeds VM limit
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

由Martin Buchholz(Google)在2010-05-09添加;由Chris Hegarty(Oracle)审查。

所以, 也许 我们可以说,最大的“安全”的数目将是 2 147 483 639Integer.MAX_VALUE - 8)和“尝试分配更大的阵列可能会导致OutOfMemoryError错误 ”。

(是的,Buchholz的独立声明不包括支持证据,因此这是对权威的有计划的上诉。即使在OpenJDK本身内,我们也可以看到类似的代码return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;表明该代码MAX_ARRAY_SIZE尚未真正使用。)


以及为什么我们需要添加-8
JohnWinter 2015年

@Pacerier。仅在使用ArrayList时不应该应用此MAX_ARRAY_SIZE吗?这与使用像int []这样的数组不同:array = new int [some_value_here]; 是不是 为什么可以将ArrayList中定义的常量应用于普通数组(用[]定义)?他们在幕后是一样的吗?
Tiago

1
@Tiago,不,代码本身与数组的最大大小无关。这只是一个要求。
Pacerier,2015年

@JohnWinter,引号指出“某些VM在数组中保留了一些标头单词”。因此,这-8是因为保留的标头字会占用字节。
Pacerier

38

实际上有两个限制。一是可为数组索引的最大元素,二是应用程序可用的内存量。根据可用内存量和其他数据结构使用的量,在达到最大可寻址数组元素之前,您可能会达到内存限制。


27

阅读本文http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays

Java被批评为不支持超过2 31 -1(约21亿)个元素的数组。这是语言的限制;Java语言规范的第10.4节指出:

数组必须由int值索引...尝试访问具有长索引值的数组组件会导致编译时错误。

支持大型阵列还需要更改JVM。这种限制在诸如集合限制为20亿个元素以及无法存储大于2 GiB的内存映射文件之类的区域中体现出来。Java还缺少真正的多维数组(由单个间接访问连续分配的单个内存块),这限制了科学和技术计算的性能。


6
Java缺少多维数组的语法糖,但是您仍然可以通过一点乘法来“拥有”它们(除非数组的总大小超过了上述限制)
kbolino

11

数组是非负整数索引,因此您可以访问的最大数组大小为Integer.MAX_VALUE。另一件事是您可以创建多大的数组。这取决于您可用的最大内存JVM和阵列的内容类型。每个数组元素都有其大小,例如。byte = 1 byteint = 4 bytesObject reference = 4 bytes (on a 32 bit system)

因此,如果您的计算机上有1 MB可用的内存,则可以分配byte[1024 * 1024]或的数组Object[256 * 1024]

回答你的问题 -您可以分配一个大小数组(最大可用内存/数组项的大小)。

摘要 -理论上,数组的最大大小为Integer.MAX_VALUE。实际上,这取决于您的内存JVM量以及已经分配给其他对象的内存量。


3

我试图创建一个像这样的字节数组

byte[] bytes = new byte[Integer.MAX_VALUE-x];
System.out.println(bytes.length);

使用此运行配置:

-Xms4G -Xmx4G

和java版本:

Openjdk版本“ 1.8.0_141”

OpenJDK运行时环境(内部版本1.8.0_141-b16)

OpenJDK 64位服务器VM(内部版本25.141-b16,混合模式)

它仅适用于x> = 2,这意味着数组的最大大小为Integer.MAX_VALUE-2

高于该值的值

线程“主”中的异常java.lang.OutOfMemoryError:请求的数组大小超出了Main.main的VM限制(Main.java:6)


2

是的,对Java数组有限制。Java使用整数作为数组的索引,JVM的最大整数存储为2 ^ 32。因此您可以在数组中存储2,147,483,647个元素。

如果您需要的长度超过最大长度,则可以使用两个不同的数组,但是建议的方法是将数据存储到文件中。因为在文件中存储数据没有限制。因为存储在存储驱动程序中但数组存储的文件存储在JVM中。JVM为程序执行提供了有限的空间。


1

arrayis (2^31)−1或的最大元素数2 147 483 647


5
Java无法分配大小数组Integer.MAX_VALUE - 1,您将收到“ java.lang.OutOfMemoryError:请求的数组大小超出VM限制”。JDK 6及更高版本中的最大元素数Integer.MAX_VALUE - 2=2147483645。–
Alexey Ivanov

0

实际上,它是java的上限,上限为2 ^ 30-4,即1073741820。不是2 ^ 31-1。Dunno为什么但是我在jdk上手动测试了它。2 ^ 30-3仍然抛出vm

编辑:固定-1至-4,在Windows jvm上检查


您正在使用32位JVM。使用64位JVM,JVM限制将接近2 ^ 31。(您还需要可用的堆空间,这不是默认的,并且会受到物理内存的影响。)
dave_thompson_085
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.