2012-01-29 12 views
5

Stavo leggendo Unveiling the java.lang.Out OfMemoryError e mi chiedevo se l'ho capito correttamente. E 'vero che se la Java VM getta unaVerrà rilevato java.lang.OutOfMemoryError anche senza mancanza di memoria?

java.lang.OutOfMemoryError: dimensione della matrice richiesta oltrepassa limite VM

Significa che la VM ha respinto la creazione di una matrice, poiché ha superato un pre-definito limite (superato il Mi piace della VM) e non perché ho esaurito la memoria nello spazio heap?

Ho ragione di dire che java.lang.OutOfMemoryError: Requested array size exceeds VM limit non indica una mancanza di memoria?

Anche se ho illimitato memoria ovunque, la Java VM potrebbe ancora lanciare una java.lang.OutOfMemoryError: Requested array size exceeds VM limit se non piace la mia richiesta di creare un array di n dimensioni?

+0

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

risposta

9

Citando Troubleshooting Guide for Java SE 6 with HotSpot VM

3.1.3 Particolare Messaggio: Requested array size exceeds VM limit (linea in grassetto è mio):

Il dettaglio messaggio Requested array size exceeds VM limit indica che l'applicazione (o le API utilizzato da tale applicazione) ha tentato di allocare una matrice che è più grande della dimensione dell'heap. Ad esempio, se un'applicazione tenta di allocare un array di 512 MB ma la dimensione massima dell'heap è 256 MB, verrà generato OutOfMemoryError con il motivo Requested array size exceeds VM limit. Nella maggior parte dei casi il problema è un problema di configurazione (dimensioni heap troppo piccole) o un errore che risulta in un'applicazione che tenta di creare un enorme array, ad esempio, quando il numero di elementi nell'array viene calcolato utilizzando un algoritmo che calcola una dimensione errata.


UPDATE: incoraggiati dalla @Pacerier ho fatto alcuni test rapido.Ho scritto un programma di esempio:

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); 
     } 
    } 
} 

ed eseguirlo con le seguenti opzioni JVM:

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

Questo è il loro significato:

  • Il mucchio è 192 MiB (-Xms192m -Xmx192m)
  • Lo spazio della giovane generazione (eden + survivor) è 64 MiB, la vecchia generazione è 128 MiB (-XX:NewRatio=2)
  • Ogni spazio superstite (su due) è 8 MiB, quindi 48 MiB è lasciato per Eden (1: 6 rapporto, -XX:SurvivorRatio=6)

Durante il test ho scoperto quanto segue:

  • Se il la matrice appena creata può essere inserita in eden (meno di 48 MiB), il programma funziona bene
  • Sorprendentemente, quando la dimensione dell'array supera la dimensione di eden, ma può essere inserita in eden e nello spazio uno spazio (tra 48 e 56 MiB), JVM può allocare un singolo oggetto su eden e survivor (sovrapponendo tw o aree). Neat!
  • Una volta che la dimensione dell'array supera l'eden + singolo sopravvissuto (oltre 56 MiB), l'oggetto appena creato viene posto direttamente nella vecchia generazione, scavalcando gli spazi eden e survivor. Questo significa anche che all'improvviso il GC completo viene eseguito sempre - molto male!
  • mi può facilmente allocare 127 Mb di dati, ma cercando di destinare 129 MiB getterà OutOfMemoryError: Java heap space

Questa è la linea di fondo - non è possibile creare un oggetto con dimensioni più grandi di vecchia generazione. Provare a farlo comporterà l'errore OutOfMemoryError: Java heap space. Quindi, quando possiamo aspettarci un terribile Requested array size exceeds VM limit?

Ho provato a eseguire lo stesso programma con oggetti molto più grandi. Colpendo il limite di lunghezza dell'array, sono passato a long[] e potrei facilmente arrivare a 7 GiB. Con 128 MiB di heap massimo dichiarato JVM stava ancora lanciando OutOfMemoryError: Java heap space (!) Sono riuscito ad attivare l'errore OutOfMemoryError: Requested array size exceeds VM limit cercando di allocare 8 GiB in un singolo oggetto. Ho provato questo su un computer Linux a 32 bit con 3 GB di memoria fisica e 1 GB di swap.

Ciò detto, probabilmente non si dovrebbe mai dare questo errore. La documentazione sembra inaccurata/obsoleta, ma è vera in una conclusione: questo è probabilmente un bug dal momento che la creazione di tali enormi array è molto rara.

+2

http: //java.sys- con.com/node/1229281 afferma che la VM può rifiutare la creazione di un array e lanciare 'OOM: La dimensione dell'array richiesto supera il limite VM' anche se c'è abbastanza memoria nell'heap per creare quell'array. Intendi dire che è sbagliato (perché la VM ** non deve ** farlo se c'è abbastanza memoria nell'heap)? – Pacerier

+0

@Pacerier: +1, penso che la documentazione sia un po 'troppo concisa qui. Il mucchio è diviso in giovani, sopravvissuti e di vecchia generazione. Immagino che l'eccezione verrà generata quando l'array non può adattarsi alla vecchia generazione (facile da testare), anche se l'intero heap è abbastanza grande. –

+0

@Pacerier: ho eseguito alcuni test e aggiornato la mia risposta in modo significativo. Dare un'occhiata! –

1

Indica la mancanza di memoria heap. Potrebbe esserci molta memoria disponibile in altre aree, ma non c'è abbastanza memoria heap per creare l'oggetto richiesto (potrebbe essere una stringa (o) semplice). Ecco un buon blog su questo topic.

Problemi correlati