Les tableaux Java ont-ils une taille maximale?

214

Y a-t-il une limite au nombre d'éléments qu'un tableau Java peut contenir? Si oui, c'est quoi?

Lézard
la source
5
Vous avez accepté une mauvaise réponse, essayez simplement d'allouer un si long tableau (et non, je ne manque pas de mémoire).
maaartinus
Étroitement liés: stackoverflow.com/questions/878309/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
La bonne réponse est stackoverflow.com/questions/31382531/…
Ivan Mamontov

Réponses:

184

Je n'ai pas vu la bonne réponse, même si c'est très facile à tester.

Dans une machine virtuelle HotSpot récente, la bonne réponse est Integer.MAX_VALUE - 5. Une fois que vous allez au-delà de cela:

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

Vous obtenez:

Exception in thread "main" java.lang.OutOfMemoryError:
  Requested array size exceeds VM limit
Kevin Bourrillion
la source
57
Je pense que l'idée de downvotes n'a de sens que si nous sommes prêts à downvote des réponses qui sont simples et tout simplement erronées . La différence de cinq octets importe-t-elle réellement dans le monde réel, NON, bien sûr que non. Mais cela m'inquiète que les gens soient prêts à donner une réponse "avec autorité" sans même essayer de voir si cela fonctionne vraiment. Quant à la limite de mémoire, eh bien, DUH. C'est comme si vous me demandiez "combien de raisins pouvez-vous manger?" et j'ai dit "eh bien, cela dépend du nombre que j'ai dans le frigo à l'époque."
Kevin Bourrillion
7
Savez-vous par hasard pourquoi il ne vous donnera pas ces cinq octets? Est-ce nécessairement quelque chose qui se produit toujours en Java, ou pourrait-il simplement être lié à la mémoire de votre ordinateur ou quelque chose?
Taymon
17
@Kevin Bourrillion: Cela semble avoir changé, en utilisant Oracle 1.7.0_07, je peux allouer jusqu'à des MAX_VALUE-2éléments. Ceci est indépendant de ce que j'alloue, et je me demande vraiment à quoi la machine virtuelle peut-elle utiliser les deux "choses" (la longueur ne tient pas sur 2 octets).
maaartinus
3
@ TomášZato au plus tard à Integer.MAX_VALUE+1, vous aurez un débordement d'entier. Les tailles de tableau en Java ne le sont intpas long; quel que soit le type de données que vous stockez dans votre tableau, octets ou références. Les chaînes ne sont que des références d'objet.
A QUIT - Anony-Mousse
8
Le nombre maximal d'éléments dans un tableau dans JDK 6 et supérieur est Integer.MAX_VALUE - 2= 2 147 483 645. Java alloue correctement un tel tableau si vous l'exécutez avec -Xmx13G. Il échoue OutOfMemoryError: Java heap spacesi vous réussissez -Xmx12G.
Alexey Ivanov
127

Ceci est (bien sûr) totalement dépendant de la machine virtuelle.

En parcourant le code source de OpenJDK 7 et 8 java.util.ArrayList, .Hashtable, .AbstractCollection, .PriorityQueueet .Vector, vous pouvez voir cette réclamation se répète:

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

qui est ajouté par Martin Buchholz (Google) le 2010-05-09 ; révisé par Chris Hegarty (Oracle).

Donc, nous pouvons probablement dire que le nombre maximum "sûr" serait de 2 147 483 639 ( Integer.MAX_VALUE - 8) et "les tentatives d'allocation de tableaux plus grands peuvent entraîner OutOfMemoryError ".

(Oui, la revendication autonome de Buchholz n'inclut pas de preuves à l'appui, il s'agit donc d'un appel calculé à l'autorité. Même au sein d'OpenJDK lui-même, nous pouvons voir du code comme celui return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;qui montre que cela MAX_ARRAY_SIZEn'a pas encore une réelle utilité.)

Pacerier
la source
Et pourquoi devons-nous ajouter -8?
JohnWinter
@Pacerier. Ce MAX_ARRAY_SIZE ne doit-il pas être appliqué uniquement lorsque vous utilisez une liste de tableaux? C'est différent d'utiliser un tableau comme int [] array = new int [some_value_here]; n'est-ce pas? Pourquoi une constante définie dans ArrayList peut-elle être appliquée à un tableau normal (défini avec [])? Sont-ils les mêmes en coulisses?
Tiago
1
@Tiago, Non, le code lui-même n'a rien à voir avec la taille maximale des tableaux. C'est juste une réclamation.
Pacerier
@JohnWinter, la citation indique "Certaines machines virtuelles réservent des mots d'en-tête dans un tableau". Donc, -8c'est dû aux octets que les mots d'en-tête réservés occuperaient.
Pacerier
38

Il y a en fait deux limites. Un, l'élément maximum indexable pour le tableau et, deux, la quantité de mémoire disponible pour votre application. Selon la quantité de mémoire disponible et la quantité utilisée par d'autres structures de données, vous pouvez atteindre la limite de mémoire avant d'atteindre l'élément de tableau adressable maximum.

tvanfosson
la source
27

En passant par cet article http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :

Java a été critiqué pour ne pas prendre en charge les tableaux de plus de 2 31 −1 (environ 2,1 milliards) d'éléments. Il s'agit d'une limitation de la langue; la spécification du langage Java, section 10.4, stipule que:

Les tableaux doivent être indexés par des valeurs int ... Une tentative d'accès à un composant de tableau avec une valeur d'index longue entraîne une erreur de compilation.

La prise en charge de baies de grande taille nécessiterait également des modifications de la JVM. Cette limitation se manifeste dans des domaines tels que les collections limitées à 2 milliards d'éléments et l'impossibilité de stocker des fichiers de mappage supérieurs à 2 Gio. Java manque également de véritables tableaux multidimensionnels (blocs de mémoire alloués de manière contiguë accédés par une seule indirection), ce qui limite les performances de l'informatique scientifique et technique.

travail
la source
6
Java n'a pas le sucre syntaxique pour les tableaux multidimensionnels, mais vous pouvez toujours les "avoir" avec un peu de multiplication (à moins que la taille totale du tableau ne dépasse la limite susmentionnée)
kbolino
11

Les tableaux sont indexés sur des nombres entiers non négatifs, donc la taille maximale du tableau à laquelle vous pouvez accéder serait Integer.MAX_VALUE. L'autre chose est la taille du tableau que vous pouvez créer. Cela dépend de la mémoire maximale disponible pour votre JVMet du type de contenu de la baie. Chaque élément du tableau a sa taille, par exemple. byte = 1 byte, int = 4 bytes,Object reference = 4 bytes (on a 32 bit system)

Donc, si vous avez de la 1 MBmémoire disponible sur votre machine, vous pouvez allouer un tableau de byte[1024 * 1024]ouObject[256 * 1024] .

Répondre à votre question - Vous pouvez allouer un tableau de taille (mémoire maximale disponible / taille de l'élément de tableau).

Résumé - Théoriquement, la taille maximale d'un tableau sera Integer.MAX_VALUE. Cela dépend pratiquement de la quantité de mémoire dont vous disposez JVMet de celle qui a déjà été allouée à d'autres objets.

Dhanuka
la source
3

J'ai essayé de créer un tableau d'octets comme celui-ci

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

Avec cette configuration d'exécution:

-Xms4G -Xmx4G

Et la version java:

Version Openjdk "1.8.0_141"

Environnement d'exécution OpenJDK (build 1.8.0_141-b16)

VM serveur OpenJDK 64 bits (build 25.141-b16, mode mixte)

Cela ne fonctionne que pour x> = 2, ce qui signifie que la taille maximale d'un tableau est Integer.MAX_VALUE-2

Des valeurs au-dessus qui donnent

Exception dans le thread "principal" java.lang.OutOfMemoryError: la taille de tableau demandée dépasse la limite de machine virtuelle sur Main.main (Main.java:6)

Vasilis Nicolaou
la source
2

Oui, il y a une limite sur le tableau java. Java utilise un entier comme index du tableau et le magasin d'entiers maximum par JVM est 2 ^ 32. vous pouvez donc stocker 2 147 483 647 éléments dans le tableau.

Si vous avez besoin de plus que la longueur maximale, vous pouvez utiliser deux tableaux différents, mais la méthode recommandée consiste à stocker les données dans un fichier. car le stockage des données dans le fichier n'a pas de limite. car les fichiers stockés dans vos pilotes de stockage mais la baie sont stockés dans JVM. JVM offre un espace limité pour l'exécution du programme.

Avinash Barde
la source
1

Nombre maximal d'éléments d'un arrayest (2^31)−1ou2 147 483 647

Bébé
la source
5
Java ne peut pas allouer de tableau de taille Integer.MAX_VALUE - 1, vous obtiendrez "java.lang.OutOfMemoryError: la taille du tableau demandée dépasse la limite de la machine virtuelle". Le nombre maximum d'éléments dans JDK 6 et au-dessus est Integer.MAX_VALUE - 2= 2 147 483 645.
Alexey Ivanov
0

En fait, c'est la limitation java qui la limite à 2 ^ 30-4 étant 1073741820. Pas 2 ^ 31-1. Je ne sais pas pourquoi mais je l'ai testé manuellement sur jdk.2 ^ 30-3 jetant toujours vm sauf

Edit: fixe -1 à -4, vérifié sur windows jvm

Fougère
la source
Vous utilisez une JVM 32 bits. Utilisez une JVM 64 bits et la limite JVM sera proche de 2 ^ 31. (Vous avez également besoin d'espace de stockage disponible, qui n'est pas la valeur par défaut, et sera affecté par votre mémoire physique.)
dave_thompson_085