Come gestire l’errore “java.lang.OutOfMemoryError: Java heap space” (64 MB di heap)

Sto scrivendo un’applicazione client Swing lato client (graphic font designer) su Java 5 . Recentemente, sto correndo in java.lang.OutOfMemoryError: Java heap space errore java.lang.OutOfMemoryError: Java heap space perché non sto conservando l’utilizzo della memoria. L’utente può aprire un numero illimitato di file e il programma mantiene gli oggetti aperti nella memoria. Dopo una rapida ricerca ho trovato Ergonomics nella 5.0 Java Virtual Machine e altri hanno detto che sulla macchina Windows la dimensione massima dell’hub di default della JVM era di 64MB .

Data questa situazione, come devo affrontare questo vincolo?

Potrei aumentare la dimensione massima dell’heap usando l’opzione da riga di comando per java, ma ciò richiederebbe la ricerca della RAM disponibile e la scrittura di alcuni programmi o script di avvio. Inoltre, l’aumento di alcuni limiti massimi non risolve il problema.

Potrei riscrivere parte del mio codice per mantenere gli oggetti sul file system frequentemente (usando il database è la stessa cosa) per liberare la memoria. Potrebbe funzionare, ma probabilmente anche molto lavoro.

Se potessi indicarmi i dettagli delle idee sopra o alcune alternative come la memoria virtuale automatica, estendendo le dimensioni dell’heap in modo dinamico , sarebbe fantastico.

Alla fine hai sempre un massimo di heap finito da usare indipendentemente dalla piattaforma su cui stai lavorando. In Windows 32 bit questo è di circa 2 GB (non in modo specifico heap ma quantità totale di memoria per processo). Succede semplicemente che Java scelga di rendere il default più piccolo (presumibilmente in modo che il programmatore non possa creare programmi che hanno allocazione di memoria in fuga senza incappare in questo problema e dover esaminare esattamente cosa stanno facendo).

Quindi questo dato ci sono diversi approcci che potresti prendere per determinare la quantità di memoria che ti serve o per ridurre la quantità di memoria che stai utilizzando. Un errore comune con i linguaggi raccolti con garbage come Java o C # è quello di conservare riferimenti a oggetti che non si utilizzano più, o allocare molti oggetti quando è ansible riutilizzarli. Finché gli oggetti hanno un riferimento a loro continueranno a utilizzare lo spazio heap in quanto il garbage collector non li eliminerà.

In questo caso è ansible utilizzare un profiler della memoria Java per determinare quali metodi nel programma stanno allocando un numero elevato di oggetti e quindi determinare se esiste un modo per assicurarsi che non vengano più referenziati o per non allocarli in primo luogo. Un’opzione che ho usato in passato è “JMP” http://www.khelekore.org/jmp/ .

Se si determina che si stanno allocando questi oggetti per un motivo ed è necessario mantenere i riferimenti (a seconda di ciò che si sta facendo potrebbe essere il caso), sarà sufficiente aumentare la dimensione massima dell’heap quando si avvia il programma. Tuttavia, una volta eseguita la profilazione della memoria e capendo come vengono assegnati gli oggetti, è necessario avere un’idea migliore della quantità di memoria necessaria.

In generale, se non è ansible garantire che il programma venga eseguito in una quantità limitata di memoria (forse in base alla dimensione dell’input) si verificherà sempre questo problema. Solo dopo aver esaurito tutto questo dovrai consultare gli oggetti di cache sul disco ecc. A questo punto dovresti avere un buon motivo per dire “Ho bisogno di Xgb di memoria” per qualcosa e non puoi aggirarlo migliorando i tuoi algoritmi o modelli di allocazione della memoria. Generalmente questo sarà solo il caso degli algoritmi che operano su dataset di grandi dimensioni (come un database o qualche programma di analisi scientifica) e quindi le tecniche come la memorizzazione nella cache e la memoria mappata diventano utili.

Esegui Java con l’opzione della riga di comando -Xmx , che imposta la dimensione massima dell’heap.

Vedi qui per i dettagli. .

È ansible specificare per progetto quanto spazio su disco desidera il tuo progetto

Di seguito è riportato per Eclipse Helios / Juno / Kepler :

Fai clic con il pulsante destro del mouse su

  Run As - Run Configuration - Arguments - Vm Arguments, 

quindi aggiungi questo

 -Xmx2048m 

Aumentare la dimensione dell’heap non è una “correzione”, è un “intonaco”, temporaneo al 100%. Crollerà di nuovo in qualche altro posto. Per evitare questi problemi, scrivere codice ad alte prestazioni.

  1. Utilizza le variabili locali laddove ansible.
  2. Assicurati di selezionare l’object corretto (EX: Selezione tra String, StringBuffer e StringBuilder)
  3. Usa un buon sistema di codice per il tuo programma (EX: Uso di variabili statiche VS variabili non statiche)
  4. Altre cose che potrebbero funzionare sul tuo codice.
  5. Prova a muoverti con multy THREADING

Grande avvertenza —- nel mio ufficio, stavamo trovando che (su alcune macchine Windows) non potevamo allocare più di 512m per l’heap Java. Ciò si è rivelato dovuto al prodotto antivirus Kaspersky installato su alcune di queste macchine. Dopo aver disinstallato il prodotto AV, abbiamo scoperto che è ansible allocare almeno 1,6 gb, ovvero, -Xmx1600m (m è obbligatorio altrimenti si verificherà un altro errore “Troppo piccolo heap iniziale”).

Non ho idea se questo accade con altri prodotti AV, ma presumibilmente questo sta accadendo perché il programma AV sta riservando un piccolo blocco di memoria in ogni spazio di indirizzamento, impedendo così una singola allocazione veramente grande.

L’argomento VM ha funzionato per me in Eclipse. Se si utilizza la versione 3.4 di eclipse, effettuare le seguenti operazioni

vai su Run --> Run Configurations --> quindi seleziona il progetto sotto maven build -> quindi seleziona la scheda “JRE” -> quindi inserisci -Xmx1024m .

In alternativa puoi eseguire Run --> Run Configurations --> select the "JRE" tab --> quindi inserisci – Xmx1024m

Ciò dovrebbe aumentare l’heap di memoria per tutte le build / progetti. Le dimensioni di memoria sopra indicate sono 1 GB. È ansible ottimizzare il modo desiderato.

Sì, con -Xmx puoi configurare più memoria per te JVM. Per essere sicuri di non perdere o sprecare memoria. Prendi un dump e usa Eclipse Memory Analyzer per analizzare il consumo di memoria.

Vorrei aggiungere raccomandazioni dall’articolo di oracle trouble shooting

Eccezione nel thread nome_file: java.lang.OutOfMemoryError: spazio heap Java

Il messaggio di dettaglio Spazio heap Java indica che l’object non può essere allocato nell’heap Java. Questo errore non implica necessariamente una perdita di memoria

Cause possibili:

  1. Problema di configurazione semplice , in cui la dimensione dell’heap specificata è insufficiente per l’applicazione.

  2. L’applicazione contiene involontariamente riferimenti a oggetti e questo impedisce che gli oggetti vengano raccolti.

  3. Uso eccessivo dei finalizzatori .

Un’altra potenziale fonte di questo errore si verifica con le applicazioni che fanno un uso eccessivo dei finalizzatori. Se una class ha un metodo finalize, allora gli oggetti di quel tipo non hanno il loro spazio recuperato al momento della raccolta dei dati inutili

Dopo la garbage collection , gli oggetti vengono messi in coda per la finalizzazione , che si verifica in un secondo momento. i finalizzatori sono eseguiti da un thread daemon che serve la coda di finalizzazione. Se il thread del finalizzatore non riesce a tenere il passo con la coda di finalizzazione, allora l’heap Java potrebbe riempirsi e questo tipo di eccezione OutOfMemoryError verrebbe generata.

Uno scenario che può causare questa situazione è quando un’applicazione crea thread ad alta priorità che fanno aumentare la coda di finalizzazione ad una velocità più veloce della velocità con cui il thread del finalizzatore sta servendo quella coda.

Segui i passaggi seguenti:

  1. Apri catalina.sh da tomcat / bin.

  2. Chnage JAVA_OPTS a

     JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC" 
  3. Riavvia il tuo gatto

Ho letto da qualche altra parte che puoi provare – cattura java.lang.OutOfMemoryError e sul blocco catch, puoi liberare tutte le risorse che conosci potrebbero usare un sacco di memoria, chiudere le connessioni e così via, quindi fare un System.gc () quindi riprova qualunque cosa stavi per fare.

Un altro modo è questo anche se, non so se questo potrebbe funzionare, ma attualmente sto testando se funzionerà sulla mia applicazione.

L’idea è di fare Garbage collection chiamando System.gc () che è noto per aumentare la memoria libera. È ansible continuare a controllare questo dopo l’esecuzione di un codice di inghiottimento della memoria.

 //Mimimum acceptable free memory you think your app needs long minRunningMemory = (1024*1024); Runtime runtime = Runtime.getRuntime(); if(runtime.freeMemory() 

Ho affrontato lo stesso problema della dimensione dell’heap java. Ho due soluzioni se usi java 5 (1.5).

Primo: -solo installa jdk1.6 e vai alle preferenze di eclipse e imposta il percorso jre di jav1 1.6 come hai installato.

2 °: -Controlla l’argomento della tua VM e lascia che sia quello che è. basta aggiungere una riga sotto di tutti gli argomenti presenti negli argomenti VM come -Xms512m -Xmx512m -XX: MaxPermSize = … m (192m).

Penso che funzionerà…

Un modo semplice per risolvere OutOfMemoryError in java è aumentare la dimensione massima dell’heap usando le opzioni JVM -Xmx512M , questo risolverà immediatamente il tuo OutOfMemoryError. Questa è la mia soluzione preferita quando ottengo OutOfMemoryError in Eclipse, Maven o ANT durante la costruzione del progetto perché in base alle dimensioni del progetto è ansible eseguire facilmente la memoria.

Ecco un esempio di aumento della dimensione massima dell’heap di JVM, Inoltre è meglio mantenere -Xmx in -Xms ration 1: 1 o 1: 1.5 se si sta impostando la dimensione dell’heap nell’applicazione java.

export JVM_ARGS="-Xms1024m -Xmx1024m"

Link di riferimento

Se è necessario monitorare l’utilizzo della memoria in fase di runtime, il pacchetto java.lang.management offre MBean che possono essere utilizzati per monitorare i pool di memoria nella VM (ad es., Spazio eden, generazione di tenured, ecc.) E anche il comportamento di garbage collection.

Lo spazio heap libero riportato da questi MBean varierà notevolmente a seconda del comportamento del GC, in particolare se l’applicazione genera molti oggetti che sono successivamente GC-ed. Un ansible approccio è quello di monitorare lo spazio heap libero dopo ogni full-GC, che potresti essere in grado di usare per prendere una decisione sulla liberazione della memoria da oggetti persistenti.

In definitiva, la soluzione migliore è limitare la conservazione della memoria il più ansible mentre le prestazioni rimangono accettabili. Come notato in precedenza, la memoria è sempre limitata, ma la tua app dovrebbe avere una strategia per affrontare l’esaurimento della memoria.

Si noti che, se necessario, in una situazione di distribuzione, considerare l’utilizzo di Java WebStart (con una versione “ondisk”, non di rete – ansible in Java 6u10 e versioni successive) in quanto consente di specificare i vari argomenti sulla JVM in una croce piattaforma.

Altrimenti è necessario un launcher specifico del sistema operativo che imposta gli argomenti necessari.

Di default per lo sviluppo JVM utilizza piccole dimensioni e una piccola configurazione per altre funzionalità correlate alle prestazioni. Ma per la produzione è ansible eseguire tuning ad esempio (Inoltre può esistere una config specifica per Application Server) -> (Se non c’è ancora abbastanza memoria per soddisfare la richiesta e l’heap ha già raggiunto la dimensione massima, si verificherà un errore OutOfMemoryError)

 -Xms set initial Java heap size -Xmx set maximum Java heap size -Xss set java thread stack size -XX:ParallelGCThreads=8 -XX:+CMSClassUnloadingEnabled -XX:InitiatingHeapOccupancyPercent=70 -XX:+UnlockDiagnosticVMOptions -XX:+UseConcMarkSweepGC -Xms512m -Xmx8192m -XX:MaxPermSize=256m (in java 8 optional) 

Ad esempio: Sulla piattaforma Linux per le impostazioni della modalità di produzione preferibili.

Dopo aver scaricato e configurato il server in questo modo http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/

1.creare il file setenv.sh nella cartella / opt / tomcat / bin /

  touch /opt/tomcat/bin/setenv.sh 

2. Aprire e scrivere questo parametro per impostare la modalità preferibile.

 nano /opt/tomcat/bin/setenv.sh export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8" export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled" export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70" export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions" export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC" export CATALINA_OPTS="$CATALINA_OPTS -Xms512m" export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m" export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M" 

3. service tomcat restart

Si noti che JVM utilizza più memoria del solo heap. Ad esempio, i metodi Java, gli stack di thread e gli handle nativi vengono allocati in memoria separatamente dall’heap e anche dalle strutture di dati interne JVM.

Se continui ad allocare e mantenere i riferimenti all’object, riempirai ogni ammontare di memoria che hai.

Un’opzione consiste nel chiudere e aprire un file trasparente quando cambiano le tabs (si tiene solo un puntatore al file e quando l’utente cambia scheda, si chiudono e si puliscono tutti gli oggetti … il file cambierà più lentamente … ma …), e forse conserva solo 3 o 4 file in memoria.

Un’altra cosa che dovresti fare è, quando l’utente apre un file, caricarlo e intercettare qualsiasi OutOfMemoryError, quindi (dato che non è ansible aprire il file) chiude quel file, pulisce i suoi oggetti e avverte l’utente che dovrebbe chiudere inutilizzato File.

La tua idea di estendere dynamicmente la memoria virtuale non risolve il problema, perché la macchina è limitata alle risorse, quindi devi stare attento e gestire i problemi di memoria (o almeno, stai attento con loro).

Un paio di suggerimenti che ho visto con perdite di memoria è:

-> Tieni presente che se metti qualcosa in una collezione e poi lo dimentichi, hai ancora un forte riferimento ad esso, quindi annulla la raccolta, puliscila o fai qualcosa con essa … se non trovi una perdita di memoria difficile da trovare.

-> Forse, l’uso di collezioni con riferimenti deboli (weakhashmap …) può aiutare con problemi di memoria, ma devi stare attento con esso, perché potresti scoprire che l’object che cerchi è stato raccolto.

-> Un’altra idea che ho trovato è quella di sviluppare una collezione persistente archiviata su oggetti di database meno utilizzati e caricati in modo trasparente. Questo sarebbe probabilmente l’approccio migliore …

Per quanto riguarda netbeans, è ansible impostare la dimensione massima dell’heap per risolvere il problema. In primo luogo, vai su “Esegui”, quindi -> “Imposta la configurazione del progetto” -> “Personalizza” -> “Esegui” della sua finestra spuntata -> “Opzione VM” -> inserisci “-Xms2048m – Xmx2048m’.

Se questo problema si verifica in Wildfly 8 e JDK1.8, è necessario specificare le impostazioni di MaxMetaSpace invece delle impostazioni di PermGen.

Ad esempio, è necessario aggiungere sotto la configurazione nel file setenv.sh di wildfly. JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"

Per ulteriori informazioni, si prega di controllare il problema Heap Wildfly