2012-01-29 16 views
5

Estaba leyendo Unveiling the java.lang.Out OfMemoryError y me preguntaba si lo he entendido correctamente. ¿Es cierto que si la máquina virtual de Java lanza una¿Encontraré java.lang.OutOfMemoryError incluso sin falta de memoria?

java.lang.OutOfMemoryError: Solicitado tamaño de la matriz excede el límite VM

Esto significa que la máquina virtual ha rechazado la creación de una matriz, ya que ha superado un pre-definido límite (superado el me gusta de la VM), y no porque me he quedado sin memoria en el espacio de montón?

¿Tengo razón al decir que java.lang.OutOfMemoryError: Requested array size exceeds VM limit no indica una falta de memoria?

Aunque tenga ilimitada memoria todas partes, la máquina virtual de Java aún podría lanzar una java.lang.OutOfMemoryError: Requested array size exceeds VM limit si no le gusta mi solicitud para crear una matriz de n tamaño?

+0

Ver http://stackoverflow.com/questions/1880687/how-to-simulate-the-out-of-memory-required-array-size-exceeds-vm-limit – skaffman

Respuesta

9

Citando Mensaje Troubleshooting Guide for Java SE 6 with HotSpot VM

3.1.3 detalle: Requested array size exceeds VM limit (en línea en negrita es mía):

El detalle mensaje Requested array size exceeds VM limit indica que la aplicación (o API utilizado por que la aplicación) intentado asigna una matriz que es más grande que el tamaño del montón. Por ejemplo, si una aplicación intenta asignar una matriz de 512 MB pero el tamaño de almacenamiento dinámico máximo es de 256 MB, se generará OutOfMemoryError con el motivo Requested array size exceeds VM limit. En la mayoría de los casos, el problema es configuración problema (tamaño de pila demasiado pequeño) o un error que da como resultado una aplicación que intenta crear un gran conjunto, por ejemplo, cuando se calcula el número de elementos en el conjunto un algoritmo que calcula un tamaño incorrecto.


ACTUALIZACIÓN: animado por el @Pacerier lo hice alguna prueba rápida.Escribí un programa de ejemplo:

public class VmLimitTest { 

    public static final int SIZE = 2; 

    public static void main(String[] args) throws InterruptedException { 
     while(true) { 
      byte[] a = new byte[SIZE * 1024 * 1024]; 
      TimeUnit.MILLISECONDS.sleep(10); 
     } 
    } 
} 

y ejecutarlo con las siguientes opciones de JVM:

-Xms192m -Xmx192m -XX:NewRatio=2 -XX:SurvivorRatio=6 -XX:+PrintGCDetails 

Esto es lo que significan:

  • Todo el montón es 192 MiB (-Xms192m -Xmx192m)
  • El espacio de la generación joven (eden + survivor) es de 64 MiB, la generación anterior es de 128 MiB (-XX:NewRatio=2)
  • Cada espacio superviviente (de dos) es 8 MiB, por lo 48 MiB se deja para eden (relación 1: 6, -XX:SurvivorRatio=6)

Mientras que la prueba descubrí la siguiente:

  • Si el matriz recién creada puede caber en eden (menos de 48 MiB), el programa funciona bien
  • Sorprendentemente, cuando el tamaño de la matriz excede el tamaño eden, pero puede caber en eden y un espacio superviviente (entre 48 y 56 MiB), JVM puede asignar un único objeto en eden y survivor (superposición de tw o áreas). ¡Ordenado!
  • Una vez que el tamaño de la matriz excede eden + superviviente individual (por encima de 56 MiB) el objeto recién creado se coloca directamente en la generación anterior, evitando los espacios de eden y survivor. Esto también significa que de repente se realiza un GC completo todo el tiempo, ¡muy mal!
  • que se puede asignar fácilmente 127 MiB de datos, sino intentar asignar 129 MiB tirará OutOfMemoryError: Java heap space

Ésta es la línea de fondo - no se puede crear un objeto con tamaño mayor de antigua generación. Si intenta hacerlo, se producirá el error OutOfMemoryError: Java heap space. Entonces, ¿cuándo podemos esperar Requested array size exceeds VM limit terrible?

Intenté ejecutar el mismo programa con objetos mucho más grandes. Al tocar el límite de longitud de la matriz, cambié a long[] y podría llegar fácilmente a 7 GiB. Con 128 MiB de max heap declarada, la JVM todavía estaba lanzando OutOfMemoryError: Java heap space (!) Logré desencadenar el error OutOfMemoryError: Requested array size exceeds VM limit tratando de asignar 8 GiB en un solo objeto. Probé esto en una computadora Linux de 32 bits con 3 GiB de memoria física y 1 GiB de intercambio.

Dicho esto, probablemente nunca deberías encontrar este error. La documentación parece inexacta/obsoleta, pero es cierta en una conclusión: esto es probablemente un error ya que la creación de matrices de este tipo es muy poco común.

+2

http: //java.sys- con.com/node/1229281 indica que la VM puede rechazar la creación de una matriz y lanzar 'OOM: el tamaño de la matriz solicitada excede el límite de VM 'incluso si hay suficiente memoria en el montón para crear la matriz. ¿Quiere decir que eso está mal (porque la VM ** no debe ** hacerlo si hay suficiente memoria en el montón)? – Pacerier

+0

@Pacerier: +1, creo que la documentación es demasiado escueta aquí. El montón está dividido en jóvenes, sobrevivientes y viejos. Supongo que se lanzará la excepción cuando la matriz no se ajuste a la generación anterior (fácil de probar), a pesar de que todo el montón es lo suficientemente grande. –

+0

@Pacerier: Hice algunas pruebas y actualicé mi respuesta significativamente. ¡Echar un vistazo! –

1

Indica la falta de memoria del montón. Puede haber suficiente memoria disponible en otras áreas, pero no hay suficiente memoria de almacenamiento dinámico para crear el objeto solicitado (podría ser una matriz (o) una cadena simple). Aquí hay un buen blog en este topic.

Cuestiones relacionadas