¿Las matrices Java tienen un tamaño máximo?

214

¿Existe un límite para la cantidad de elementos que puede contener una matriz Java? Si es así, ¿qué es?

Lagartija
fuente
55
Has aceptado una respuesta incorrecta, solo intenta asignar una matriz tan larga (y no, no me estoy quedando sin memoria).
maaartinus
Muy relacionado: stackoverflow.com/questions/878309/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
La respuesta correcta es stackoverflow.com/questions/31382531/…
Ivan Mamontov

Respuestas:

184

No he visto la respuesta correcta, aunque es muy fácil de probar.

En una VM HotSpot reciente, la respuesta correcta es Integer.MAX_VALUE - 5. Una vez que vayas más allá de eso:

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

Usted obtiene:

Exception in thread "main" java.lang.OutOfMemoryError:
  Requested array size exceeds VM limit
Kevin Bourrillion
fuente
57
Creo que la idea de votos negativos no tiene sentido a menos que estemos dispuestos a votar negativamente las respuestas que son claras y simplemente incorrectas . ¿La diferencia de cinco bytes realmente importa en el mundo real? NO, por supuesto que no. Pero me preocupa que la gente esté dispuesta a dar una respuesta "autoritaria" sin siquiera tratar de ver si realmente funciona. En cuanto al límite de memoria, bueno, DUH. Es como si me preguntaras "¿cuántas uvas puedes comer?" y dije "bueno, depende de cuántos tenga en el refrigerador en ese momento".
Kevin Bourrillion
77
¿Sabes por qué no te dará esos cinco bytes? ¿Es esto necesariamente algo que siempre sucede en Java, o podría estar relacionado con la memoria de su computadora o algo así?
Taymon
17
@Kevin Bourrillion: Esto parece haber cambiado, usando Oracle 1.7.0_07 puedo asignar hasta MAX_VALUE-2elementos. Esto es independiente de lo que asigno, y realmente me pregunto para qué puede usar la VM las dos "cosas" (la longitud no cabe en 2 bytes).
maaartinus
3
@ TomášZato lo último en Integer.MAX_VALUE+1, tendrá un desbordamiento de enteros. Los tamaños de matriz en Java son int, no long; no importa qué tipo de datos almacene en su matriz, bytes o referencias. Las cadenas son solo referencias de objetos.
HA SALIDO - Anony-Mousse
8
El número máximo de elementos en una matriz en JDK 6 y superior es Integer.MAX_VALUE - 2= 2 147 483 645. Java asigna con éxito dicha matriz si la ejecuta -Xmx13G. Falla OutOfMemoryError: Java heap spacesi pasas -Xmx12G.
Alexey Ivanov
127

Esto es (por supuesto) totalmente dependiente de VM.

La navegación por el código fuente de OpenJDK 7 y 8 java.util.ArrayList, .Hashtable, .AbstractCollection, .PriorityQueue, y .Vector, se puede ver esta afirmación se repite:

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

que fue agregado por Martin Buchholz (Google) el 2010-05-09 ; revisado por Chris Hegarty (Oracle).

Entonces, probablemente podemos decir que el número "seguro" máximo sería 2 147 483 639 ( Integer.MAX_VALUE - 8) y "los intentos de asignar matrices más grandes pueden resultar en OutOfMemoryError ".

(Sí, el reclamo independiente de Buchholz no incluye evidencia de respaldo, por lo que esta es una apelación calculada a la autoridad. Incluso dentro de OpenJDK, podemos ver un código como el return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;que muestra que MAX_ARRAY_SIZEaún no tiene un uso real ).

Pacerier
fuente
¿Y por qué necesitamos agregar -8?
JohnWinter
@Pacerier. ¿No debería aplicarse este MAX_ARRAY_SIZE solo cuando está utilizando una ArrayList? Eso es diferente de usar una matriz como int [] array = new int [some_value_here]; no es asi ¿Por qué se puede aplicar una constante definida en ArrayList a una matriz normal (definida con [])? ¿Son lo mismo detrás de escena?
Tiago
1
@Tiago, No, el código en sí no tiene nada que ver con el tamaño máximo de las matrices. Es solo un reclamo.
Pacerier
@ JohnWinter, La cita dice "Algunas máquinas virtuales reservan algunas palabras de encabezado en una matriz". Entonces, esto -8se debe a los bytes que ocuparían las palabras de encabezado reservadas.
Pacerier
38

En realidad hay dos límites. Uno, el elemento máximo indexable para la matriz y, dos, la cantidad de memoria disponible para su aplicación. Dependiendo de la cantidad de memoria disponible y la cantidad utilizada por otras estructuras de datos, puede alcanzar el límite de memoria antes de alcanzar el elemento de matriz máximo direccionable.

tvanfosson
fuente
27

Pasando por este artículo http://en.wikipedia.org/wiki/Criticism_of_Java#Large_arrays :

Java ha sido criticado por no admitir matrices de más de 2 31 −1 (aproximadamente 2,1 mil millones) de elementos. Esta es una limitación del idioma; La Especificación del lenguaje Java, Sección 10.4, establece que:

Las matrices deben estar indexadas por valores int ... Un intento de acceder a un componente de matriz con un valor de índice largo da como resultado un error en tiempo de compilación.

El soporte de matrices grandes también requeriría cambios en la JVM. Esta limitación se manifiesta en áreas tales como las colecciones que se limitan a 2 mil millones de elementos y la incapacidad de memoria para asignar archivos de más de 2 GiB. Java también carece de matrices multidimensionales verdaderas (bloques individuales de memoria asignados de forma contigua a los que se accede mediante una sola indirección), lo que limita el rendimiento de la informática científica y técnica.

trabajando
fuente
66
Java carece del azúcar sintáctico para las matrices multidimensionales, pero aún puede "tenerlas" con un poco de multiplicación (a menos que el tamaño total de la matriz supere el límite mencionado anteriormente)
kbolino
11

Las matrices son números enteros no negativos indexados, por lo que el tamaño máximo de matriz a la que puede acceder sería Integer.MAX_VALUE. La otra cosa es la gran variedad que puede crear. Depende de la memoria máxima disponible para usted JVMy del tipo de contenido de la matriz. Cada elemento de la matriz tiene su tamaño, por ejemplo. byte = 1 byte` int = 4 bytes`Object reference = 4 bytes (on a 32 bit system)

Entonces, si tiene 1 MBmemoria disponible en su máquina, puede asignar una matriz de byte[1024 * 1024]o Object[256 * 1024].

Respuesta a su pregunta : puede asignar una matriz de tamaño (memoria máxima disponible / tamaño del elemento de matriz).

Resumen : teóricamente, el tamaño máximo de una matriz será Integer.MAX_VALUE. Prácticamente depende de la cantidad de memoria que JVMtenga y la cantidad que ya se haya asignado a otros objetos.

Dhanuka
fuente
3

Traté de crear una matriz de bytes como esta

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

Con esta configuración de ejecución:

-Xms4G -Xmx4G

Y la versión de Java:

Openjdk versión "1.8.0_141"

OpenJDK Runtime Environment (compilación 1.8.0_141-b16)

OpenJDK 64-Bit Server VM (compilación 25.141-b16, modo mixto)

Solo funciona para x> = 2, lo que significa que el tamaño máximo de una matriz es Integer.MAX_VALUE-2

Valores superiores que dan

Excepción en el subproceso "main" java.lang.OutOfMemoryError: el tamaño de la matriz solicitada excede el límite de VM en Main.main (Main.java:6)

Vasilis Nicolaou
fuente
2

Sí, hay límite en java array. Java utiliza un número entero como índice de la matriz y el almacenamiento máximo de números enteros por JVM es 2 ^ 32. para que pueda almacenar 2,147,483,647 elementos en la matriz.

En caso de que necesite más de la longitud máxima, puede usar dos matrices diferentes, pero el método recomendado es almacenar datos en un archivo. porque almacenar datos en el archivo no tiene límite. porque los archivos almacenados en sus controladores de almacenamiento pero matriz se almacenan en JVM. JVM proporciona espacio limitado para la ejecución del programa.

Avinash Barde
fuente
1

Número máximo de elementos de un arrayes (2^31)−1o2 147 483 647

Bebé
fuente
55
Java no puede asignar una matriz de tamaño Integer.MAX_VALUE - 1, obtendrá "java.lang.OutOfMemoryError: el tamaño de la matriz solicitada excede el límite de VM". El número máximo de elementos en JDK 6 y superiores es Integer.MAX_VALUE - 2= 2 147 483 645.
Alexey Ivanov
0

En realidad, es una limitación de Java que lo limita a 2 ^ 30-4 siendo 1073741820. No es 2 ^ 31-1. No sé por qué, pero lo probé manualmente en jdk. 2 ^ 30-3 todavía lanzando vm excepto

Editar: arreglado -1 a -4, marcado en Windows JVM

Helecho
fuente
Estás utilizando una JVM de 32 bits. Utilice una JVM de 64 bits y el límite de JVM estará cerca de 2 ^ 31. (También necesita espacio de almacenamiento dinámico disponible, que no es el valor por defecto, y se verán afectados por la memoria física.)
dave_thompson_085