Haben Java-Arrays eine maximale Größe?

214

Gibt es eine Begrenzung für die Anzahl der Elemente, die ein Java-Array enthalten kann? Wenn ja, was ist das?

Eidechse
quelle
5
Sie haben eine falsche Antwort akzeptiert. Versuchen Sie einfach, ein so langes Array zuzuweisen (und nein, mir geht nicht der Speicher aus).
Maaartinus
Eng verwandt: stackoverflow.com/questions/878309/…
Ciro Santilli 6 冠状 病. 事件 6
Die richtige Antwort ist stackoverflow.com/questions/31382531/…
Ivan Mamontov

Antworten:

184

Ich habe nicht die richtige Antwort gesehen, obwohl es sehr einfach zu testen ist.

In einer aktuellen HotSpot-VM lautet die richtige Antwort Integer.MAX_VALUE - 5. Sobald Sie darüber hinausgehen:

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

Du erhältst:

Exception in thread "main" java.lang.OutOfMemoryError:
  Requested array size exceeds VM limit
Kevin Bourrillion
quelle
57
Ich denke, die Idee von Abstimmungen macht keinen Sinn, es sei denn, wir sind bereit, Antworten, die schlicht und einfach falsch sind, abzulehnen . Ist der Unterschied von fünf Bytes in der realen Welt tatsächlich wichtig, NEIN, natürlich nicht. Aber es geht mich an, dass die Leute bereit sind, eine Antwort "autoritativ" zu geben, ohne es zu versuchen, um zu sehen, ob es wirklich funktioniert. Was das Speicherlimit betrifft, so ist DUH. Das ist so, als hättest du mich gefragt: "Wie viele Trauben kannst du essen?" und ich sagte: "Nun, es hängt davon ab, wie viele ich gerade im Kühlschrank habe."
Kevin Bourrillion
7
Weißt du zufällig, warum es dir diese fünf Bytes nicht gibt? Ist dies notwendigerweise etwas, das immer in Java passiert, oder könnte es nur mit dem Speicher Ihres Computers zusammenhängen oder so?
Taymon
17
@ Kevin Bourrillion: Dies scheint sich geändert zu haben. Mit Oracle 1.7.0_07 kann ich MAX_VALUE-2Elemente zuordnen . Dies ist unabhängig von dem, was ich zuordne, und ich frage mich wirklich, wofür die VM die beiden "Dinge" verwenden kann (die Länge passt nicht in 2 Bytes).
Maaartinus
3
@ TomášZato spätestens um Integer.MAX_VALUE+1, Sie werden einen ganzzahligen Überlauf haben. Array-Größen in Java sind intnicht long; Unabhängig davon, welchen Datentyp Sie in Ihrem Array, Ihren Bytes oder Referenzen speichern. Zeichenfolgen sind nur Objektreferenzen.
Hat aufgehört - Anony-Mousse
8
Die maximale Anzahl von Elementen in einem Array in JDK 6 und höher beträgt Integer.MAX_VALUE - 2= 2 147 483 645. Java weist ein solches Array erfolgreich zu, wenn Sie es mit ausführen -Xmx13G. Es schlägt fehl, OutOfMemoryError: Java heap spacewenn Sie bestehen -Xmx12G.
Alexey Ivanov
127

Dies ist (natürlich) vollständig VM-abhängig.

Browsing durch den Quellcode von OpenJDK 7 und 8 java.util.ArrayList, .Hashtable, .AbstractCollection, .PriorityQueue, und .Vectorkönnen Sie sehen , diese Forderung wiederholt werden:

/**
 * 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;

welches von Martin Buchholz (Google) am 09.05.2010 hinzugefügt wird ; rezensiert von Chris Hegarty (Oracle).

Daher können wir wahrscheinlich sagen, dass die maximale "sichere" Anzahl 2 147 483 639 ( Integer.MAX_VALUE - 8) beträgt und "Versuche, größere Arrays zuzuweisen, zu OutOfMemoryError führen können ".

(Ja, Buchholz 'eigenständige Behauptung enthält keine Belege, daher handelt es sich um einen kalkulierten Aufruf an die Behörde. Selbst innerhalb von OpenJDK selbst können wir Code sehen, return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;der zeigt, dass er MAX_ARRAY_SIZEnoch keinen wirklichen Nutzen hat.)

Pacerier
quelle
Und warum müssen wir hinzufügen -8?
JohnWinter
@ Pacerier. Sollte diese MAX_ARRAY_SIZE nicht nur angewendet werden, wenn Sie eine ArrayList verwenden? Das unterscheidet sich von der Verwendung eines Arrays wie int [] array = new int [some_value_here]; ist es nicht? Warum kann eine in ArrayList definierte Konstante auf ein normales Array angewendet werden (definiert mit [])? Sind sie hinter den Kulissen gleich?
Tiago
1
@Tiago, Nein, der Code selbst hat nichts mit der maximalen Größe von Arrays zu tun. Es ist nur eine Behauptung.
Pacerier
@ JohnWinter, Das Zitat besagt "Einige VMs reservieren einige Header-Wörter in einem Array". Das -8liegt also an den Bytes, die die reservierten Header-Wörter belegen würden.
Pacerier
38

Es gibt tatsächlich zwei Grenzen. Erstens das maximale für das Array indizierbare Element und zweitens die für Ihre Anwendung verfügbare Speichermenge. Abhängig von der verfügbaren Speichermenge und der von anderen Datenstrukturen verwendeten Speichermenge können Sie die Speichergrenze erreichen, bevor Sie das maximal adressierbare Array-Element erreichen.

Tvanfosson
quelle
27

Gehen Sie diesen Artikel durch http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :

Java wurde dafür kritisiert, dass es keine Arrays mit mehr als 2 31 -1 (ungefähr 2,1 Milliarden) Elementen unterstützt. Dies ist eine Einschränkung der Sprache; In der Java-Sprachspezifikation, Abschnitt 10.4, heißt es:

Arrays müssen durch int-Werte indiziert werden ... Ein Versuch, auf eine Array-Komponente mit einem langen Indexwert zuzugreifen, führt zu einem Fehler bei der Kompilierung.

Die Unterstützung großer Arrays würde auch Änderungen an der JVM erfordern. Diese Einschränkung äußert sich in Bereichen wie der Beschränkung von Sammlungen auf 2 Milliarden Elemente und der Unfähigkeit, Speicherzuordnungsdateien mit mehr als 2 GiB zu speichern. Java fehlen auch echte mehrdimensionale Arrays (zusammenhängend zugewiesene einzelne Speicherblöcke, auf die durch eine einzelne Indirektion zugegriffen wird), was die Leistung für wissenschaftliches und technisches Rechnen einschränkt.

Arbeiten
quelle
6
Java fehlt der syntaktische Zucker für mehrdimensionale Arrays, aber Sie können sie immer noch mit ein wenig Multiplikation "haben" (es sei denn, die Gesamtgröße des Arrays hat die oben genannte Grenze überschritten)
kbolino
11

Arrays sind nicht negativ ganzzahlig indiziert, sodass Sie maximal auf die Arraygröße zugreifen können Integer.MAX_VALUE. Die andere Sache ist, wie großes Array Sie erstellen können. Dies hängt vom maximal verfügbaren Speicher JVMund dem Inhaltstyp des Arrays ab. Jedes Array-Element hat beispielsweise seine Größe. byte = 1 byte, int = 4 bytes,Object reference = 4 bytes (on a 32 bit system)

Wenn 1 MBauf Ihrem Computer also Speicher verfügbar ist, können Sie ein Array von byte[1024 * 1024]oder zuweisen Object[256 * 1024].

Beantwortung Ihrer Frage - Sie können ein Array mit einer Größe zuweisen (maximal verfügbarer Speicher / Größe des Array-Elements).

Zusammenfassung - Theoretisch ist die maximale Größe eines Arrays Integer.MAX_VALUE. Praktisch hängt es davon ab, wie viel Speicher Sie JVMhaben und wie viel davon bereits anderen Objekten zugewiesen wurde.

Dhanuka
quelle
3

Ich habe versucht, ein solches Byte-Array zu erstellen

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

Mit dieser Laufkonfiguration:

-Xms4G -Xmx4G

Und Java-Version:

Openjdk-Version "1.8.0_141"

OpenJDK-Laufzeitumgebung (Build 1.8.0_141-b16)

OpenJDK 64-Bit-Server-VM (Build 25.141-b16, gemischter Modus)

Es funktioniert nur für x> = 2, was bedeutet, dass die maximale Größe eines Arrays Integer.MAX_VALUE-2 ist

Werte darüber geben

Ausnahme im Thread "main" java.lang.OutOfMemoryError: Die angeforderte Arraygröße überschreitet das VM-Limit bei Main.main (Main.java:6).

Vasilis Nicolaou
quelle
2

Ja, das Java-Array ist begrenzt. Java verwendet eine Ganzzahl als Index für das Array und der maximale Ganzzahlspeicher von JVM beträgt 2 ^ 32. Sie können also 2.147.483.647 Elemente im Array speichern.

Wenn Sie mehr als die maximale Länge benötigen, können Sie zwei verschiedene Arrays verwenden. Die empfohlene Methode besteht jedoch darin, Daten in einer Datei zu speichern. weil das Speichern von Daten in der Datei keine Begrenzung hat. weil Dateien, die in Ihren Speichertreibern, aber im Array gespeichert sind, in JVM gespeichert sind. JVM bietet begrenzten Speicherplatz für die Programmausführung.

Avinash Barde
quelle
1

Maximale Anzahl von Elementen eines arrayist (2^31)−1oder2 147 483 647

Baby
quelle
5
Java kann kein Array mit einer Größe zuweisen Integer.MAX_VALUE - 1. Sie erhalten "java.lang.OutOfMemoryError: Angeforderte Arraygröße überschreitet VM-Grenze". Die maximale Anzahl von Elementen in JDK 6 und höher ist Integer.MAX_VALUE - 2= 2 147 483 645.
Alexey Ivanov
0

Tatsächlich ist es eine Java-Beschränkung, die es auf 2 ^ 30-4 begrenzt und 1073741820 ist. Nicht 2 ^ 31-1. Keine Ahnung warum, aber ich habe es manuell auf JDK getestet. 2 ^ 30-3 wirft immer noch vm außer

Bearbeiten: -1 bis -4 behoben, unter Windows JVM aktiviert

Ferned
quelle
Sie verwenden eine 32-Bit-JVM. Verwenden Sie eine 64-Bit-JVM, und die JVM-Grenze liegt nahe bei 2 ^ 31. (Sie benötigen auch Heap-Speicherplatz, was nicht die Standardeinstellung ist und von Ihrem physischen Speicher beeinflusst wird.)
dave_thompson_085