java.lang.OutOfMemoryError: spazio heap Java


97

Ricevo il seguente errore durante l'esecuzione di un programma multi-threading

java.lang.OutOfMemoryError: Java heap space

L'errore precedente si è verificato in uno dei thread.

  1. Per quanto ne so, lo spazio Heap è occupato solo da variabili di istanza. Se è corretto, allora perché questo errore si è verificato dopo aver eseguito correttamente per un po 'di tempo poiché lo spazio per le variabili di istanza viene assegnato al momento della creazione dell'oggetto.

  2. C'è un modo per aumentare lo spazio dell'heap?

  3. Quali modifiche dovrei apportare al mio programma in modo che occupi meno spazio nell'heap?


Risposte:


105

Se vuoi aumentare il tuo spazio di heap, puoi usare java -Xms<initial heap size> -Xmx<maximum heap size>sulla riga di comando. Per impostazione predefinita, i valori si basano sulla versione di JRE e sulla configurazione del sistema. Puoi trovare ulteriori informazioni sulle opzioni VM sul sito Web Java .

Tuttavia, consiglierei di profilare la tua applicazione per scoprire perché la dimensione dell'heap viene consumata. NetBeans ha un ottimo profiler incluso con esso. Credo che usi il jvisualvmsotto il cofano. Con un profiler, puoi provare a trovare dove vengono creati molti oggetti, quando gli oggetti vengono raccolti e altro ancora.


1
Sto usando Netbeans ma non so come usare il profiler. Vorrei saperne di più sul profiler in modo da poterlo utilizzare per trovare perdite di memoria nella mia applicazione.
Yatendra Goel,

Ho aggiunto un collegamento a una pagina del sito NetBeans ( profiler.netbeans.org ) che ha un'ottima documentazione sul profilo, dalle basi fino all'uso più avanzato.
Thomas Owens,

I valori predefiniti cambiano con le versioni java, sarebbe bello includere queste informazioni nella risposta.
Dariusz

Ho appena risolto un problema simile e provato per la prima volta: java -jar division.jar -Xmx512m -Xms512m - questo mi dà lo stesso errore ma quando lo faccio in questo modo: java -Xmx512m -Xms512m -jar division.jar - va tutto bene. Quindi anche l'ordine dei parametri è importante.
hipokito

@hipokito Gli argomenti dopo che il file jar sono passati al metodo main () del file jar come args []
Asu

29

1.- Sì, ma si riferisce praticamente all'intera memoria utilizzata dal tuo programma.

2.- Sì, vedere le opzioni di Java VM

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

Cioè

java -Xmx2g assegna 2 gigabyte di RAM al massimo alla tua app

Ma dovresti prima vedere se non hai una perdita di memoria.

3.- Dipende dal programma. Prova a individuare perdite di memoria. Sarebbe difficile rispondere a questa domanda. Ultimamente puoi profilare usando JConsole per cercare di scoprire dove va a finire la tua memoria


mentre quale (vero);)
Gal Bracha

8

Potresti voler guardare questo sito per saperne di più sulla memoria nella JVM: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

Ho trovato utile usare visualgc per vedere come si riempiono le diverse parti del modello di memoria, per determinare cosa cambiare.

È difficile determinare quale parte della memoria è stata riempita, quindi visualgc, poiché potresti voler cambiare solo la parte che ha un problema, piuttosto che dire semplicemente,

Bene! Darò 1G di RAM alla JVM.

Cerca di essere più preciso su ciò che stai facendo, a lungo termine probabilmente troverai il programma migliore per questo.

Per determinare dove potrebbe essere la perdita di memoria puoi usare i test unitari per quello, testando qual'era la memoria prima del test e dopo, e se c'è un cambiamento troppo grande, potresti volerlo esaminare, ma, è necessario eseguire il controllo mentre il test è ancora in esecuzione.


6

Per aumentare la dimensione dell'heap è possibile utilizzare l'argomento -Xmx all'avvio di Java; per esempio

-Xmx256M


6
  1. Per quanto ne so, lo spazio Heap è occupato solo da variabili di istanza. Se è corretto, allora perché questo errore si è verificato dopo aver eseguito correttamente per un po 'di tempo poiché lo spazio per le variabili di istanza viene assegnato al momento della creazione dell'oggetto.

Ciò significa che stai creando continuamente più oggetti nella tua applicazione per un periodo di tempo. I nuovi oggetti verranno archiviati nella memoria heap e questo è il motivo per la crescita della memoria heap.

Heap non contiene solo variabili di istanza. Memorizzerà tutti i tipi di dati non primitivi (oggetti). La durata di vita di questi oggetti può essere breve (blocco del metodo) o lunga (fino a quando non viene fatto riferimento all'oggetto nell'applicazione)

  1. C'è un modo per aumentare lo spazio dell'heap?

Sì. Dai un'occhiata a questo articolo di Oracle per maggiori dettagli.

Esistono due parametri per impostare la dimensione dell'heap:

-Xms:, che imposta la dimensione dell'heap iniziale e minima

-Xmx:, che imposta la dimensione massima dell'heap

  1. Quali modifiche dovrei apportare al mio programma in modo che occupi meno spazio nell'heap?

Dipende dalla tua applicazione.

  1. Impostare la memoria heap massima in base ai requisiti dell'applicazione

  2. Non causare perdite di memoria nella tua applicazione

  3. Se trovi perdite di memoria nella tua applicazione, trova la causa principale con l'aiuto di strumenti di profiling come MAT , Visual VM , jconsole ecc. Una volta individuata la causa principale, correggi le perdite.

Note importanti da Oracle articolo

Causa: il messaggio dettagliato Spazio heap Java indica che non è stato possibile allocare l'oggetto nell'heap Java. Questo errore non implica necessariamente una perdita di memoria.

Possibili ragioni:

  1. Configurazione impropria (non allocare memoria sufficiente)
  2. L'applicazione trattiene involontariamente i riferimenti agli oggetti e ciò impedisce che gli oggetti vengano raccolti in modo indesiderato
  3. Applicazioni che fanno un uso eccessivo di finalizzatori. Se una classe ha un metodo finalize, gli oggetti di quel tipo non hanno il loro spazio recuperato al momento della garbage collection. Se il thread del finalizzatore non riesce a tenere il passo, con la coda di finalizzazione, l'heap Java potrebbe riempirsi e verrebbe generato questo tipo di eccezione OutOfMemoryError .

In una nota diversa, usa algoritmi di raccolta dei rifiuti migliori ( CMS o G1GC )

Dai un'occhiata a questa domanda per comprendere G1GC


5
  1. Nella maggior parte dei casi, il codice non è ottimizzato. Rilascia quegli oggetti che pensi non saranno più necessari. Evita ogni volta la creazione di oggetti nel tuo ciclo. Prova a usare le cache. Non so come sta andando la tua applicazione. Ma nella programmazione si applica anche una regola della vita normale

    Prevenire è meglio che curare. "Non creare oggetti non necessari"


3
  1. Le variabili locali si trovano nello stack. Lo spazio dell'heap è occupato da oggetti.

  2. Puoi usare l' -Xmxopzione.

  3. Fondamentalmente lo spazio dell'heap viene utilizzato ogni volta che si alloca un nuovo oggetto newe viene liberato un po 'di tempo dopo che l'oggetto non è più referenziato. Quindi assicurati di non conservare riferimenti a oggetti che non ti servono più.


1

No, penso che tu stia pensando allo spazio dello stack. Lo spazio dell'heap è occupato da oggetti. Il modo per aumentarlo è -Xmx256m, sostituendo il 256 con l'importo necessario sulla riga di comando.


1

Per evitare questa eccezione, se stai usando JUnit e Spring prova ad aggiungerlo in ogni classe di test:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

0

In netbeans, vai alla barra degli strumenti "Esegui", -> "Imposta configurazione progetto" -> "Personalizza" -> "Esegui" della finestra visualizzata -> "Opzione VM" -> compila "-Xms2048m -Xmx2048m '. Potrebbe risolvere il problema delle dimensioni dell'heap.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.