Domanda

Sto scrivendo un lato client Oscillazione applicazione (designer grafico dei caratteri) attiva Giava5.Recentemente, mi sto imbattuto in java.lang.OutOfMemoryError: Java heap space errore perché non sono prudente sull'utilizzo della memoria.L'utente può aprire un numero illimitato di file e il programma mantiene gli oggetti aperti in memoria.Dopo una rapida ricerca ho trovato Ergonomia nella Java Virtual Machine 5.0 e altri dicono che sulla macchina Windows la dimensione heap massima predefinita della JVM è come 64MB.

Data questa situazione, come devo affrontare questo vincolo?

Potrei aumentare il dimensione massima dell'heap utilizzando riga di comando opzione per Java, ma ciò richiederebbe di capire la RAM disponibile e scrivere qualche programma o script di avvio.Inoltre, aumentando ad alcuni finito massimo no in definitiva sbarazzarsi del problema.

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

Se potessi indicarmi i dettagli delle idee di cui sopra o alcune alternative simili memoria virtuale automatica, estendendo dinamicamente la dimensione dell'heap, sarebbe fantastico.

È stato utile?

Soluzione

Alla fine hai sempre un limite massimo di heap da utilizzare, indipendentemente dalla piattaforma su cui stai utilizzando.In Windows a 32 bit questo è in giro 2GB (non specificamente heap ma quantità totale di memoria per processo).Accade semplicemente che Java scelga di ridurre il valore predefinito (presumibilmente in modo che il programmatore non possa creare programmi con un'allocazione di memoria fuori controllo senza incorrere in questo problema e dover esaminare esattamente cosa stanno facendo).

Detto questo, ci sono diversi approcci che potresti adottare per determinare la quantità di memoria necessaria o per ridurre la quantità di memoria che stai utilizzando.Un errore comune con i linguaggi Garbage Collection come Java o C# è quello di mantenere i riferimenti agli oggetti che si non più stai utilizzando o assegnando molti oggetti quando potresti riutilizzo loro invece.Finché gli oggetti avranno un riferimento ad essi, continueranno a utilizzare lo spazio heap poiché il Garbage Collector non li eliminerà.

In questo caso è possibile utilizzare un memory profiler 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 determini che stai allocando questi oggetti per un motivo e devi mantenere i riferimenti (a seconda di cosa stai facendo, potrebbe essere il caso), dovrai solo aumentare la dimensione massima dell'heap quando avvii il programma.Tuttavia, una volta eseguita la profilazione della memoria e compreso come vengono allocati gli oggetti, dovresti avere un'idea migliore della quantità di memoria necessaria.

In generale, se non puoi garantire che il tuo programma verrà eseguito in una quantità limitata di memoria (forse a seconda della dimensione dell'input), ti imbatterai sempre in questo problema.Solo dopo aver esaurito tutto ciò dovrai esaminare la memorizzazione nella cache degli oggetti su disco, ecc.A questo punto dovresti avere un'ottima ragione per dire "Ho bisogno di Xgb di memoria" per qualcosa e non puoi aggirare il problema migliorando i tuoi algoritmi o i modelli di allocazione della memoria.Generalmente questo sarà solo il caso degli algoritmi che operano su set di dati di grandi dimensioni (come un database o qualche programma di analisi scientifica) e quindi tecniche come il caching e l'IO mappato in memoria diventano utili.

Altri suggerimenti

Esegui Java con l'opzione della riga di comando -Xmx, che imposta il massimo dimensione dell'heap.

Vedi qui per i dettagli.

Potresti specificare per proietta quanto spazio heap richiede il tuo progetto

Di seguito è per Eclissi di Helios/Giunone/Kepler:

Fare clic con il tasto 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%.Si bloccherà di nuovo da qualche altra parte.Per evitare questi problemi, scrivere codice ad alte prestazioni.

  1. Utilizzare variabili locali ove possibile.
  2. Assicurati di selezionare l'oggetto corretto (ES:Selezione tra String, StringBuffer e StringBuilder)
  3. Utilizza un buon sistema di codice per il tuo programma (ES:Utilizzando variabili statiche VS variabili non statiche)
  4. Altre cose che potrebbero funzionare sul tuo codice.
  5. Prova a muoverti con più FILETTATURA

Grande avvertimento ---- nel mio ufficio, stavamo scoprendo che (su alcune macchine Windows) non potevamo allocare più di 512 m per l'heap Java.Si è scoperto che ciò era dovuto al prodotto antivirus Kaspersky installato su alcune di queste macchine.Dopo aver disinstallato il prodotto AV, abbiamo scoperto che potevamo allocare almeno 1,6 GB, ovvero -Xmx1600m (m è obbligatorio altrimenti porterà a un altro errore "Heap iniziale troppo piccolo") funziona.

Non ho idea se ciò accada con altri prodotti AV, ma presumibilmente ciò accade perché il programma AV riserva un piccolo blocco di memoria in ogni spazio di indirizzi, impedendo così un'unica allocazione veramente grande.

Gli argomenti VM hanno funzionato per me in Eclipse.Se stai utilizzando la versione 3.4 di Eclipse, procedi come segue

vai a Run --> Run Configurations --> quindi seleziona il progetto in Maven build --> quindi seleziona la scheda "JRE" --> quindi inserisci -Xmx1024m.

In alternativa potresti farlo Run --> Run Configurations --> select the "JRE" tab --> quindi inserisci -Xmx1024m

Ciò dovrebbe aumentare l'heap di memoria per tutte le build/progetti.La dimensione della memoria sopra indicata è 1 GB.Puoi ottimizzare come preferisci.

Sì, con -Xmx puoi configurare più memoria per la tua JVM.Per essere sicuri di non perdere o sprecare memoria.Fai un heap dump e usalo l'analizzatore di memoria Eclipse per analizzare il consumo di memoria.

Vorrei aggiungere consigli da Oracle Risoluzione dei problemi articolo.

Eccezione nel thread nome_thread: errore java.lang.OutOfMemory:Spazio heap Java

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

Cause possibili:

  1. Semplice problema di configurazione, dove la dimensione heap specificata non è sufficiente per l'applicazione.

  2. L'applicazione contiene involontariamente riferimenti a oggetti, e questo impedisce che gli oggetti vengano sottoposti a Garbage Collection.

  3. Uso eccessivo di finalizzatori.

Un'altra potenziale fonte di questo errore si presenta con le applicazioni che fanno un uso eccessivo di finalizzatori.Se una classe ha un metodo finalize, gli oggetti di quel tipo non avranno il loro spazio recuperato al momento della raccolta dei rifiuti

Dopo raccolta dei rifiuti, gli oggetti vengono messi in coda finalizzazione, che avviene in un secondo momento. finalizzatori vengono eseguiti da un thread demone che serve la coda di finalizzazione.Se la finalizzatore thread non riesce a tenere il passo con la coda di finalizzazione, quindi l'heap Java potrebbe riempirsi e questo tipo di Errore di memoria esaurita verrebbe lanciata un'eccezione.

Uno scenario che può causare questa situazione è la creazione di un'applicazione thread ad alta priorità che causano il finalizzazione coda per aumentare a una velocità maggiore della velocità con cui il thread del finalizzatore serve quella coda.

Segui i passaggi seguenti:

  1. Aprire catalina.sh da Tomcat/bin.

  2. Cambia JAVA_OPTS in

    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

Un modo semplice per risolvere OutOfMemoryError in Java consiste nell'aumentare la dimensione massima dell'heap utilizzando le opzioni JVM -Xmx512M, questo risolverà immediatamente il tuo OutOfMemoryError.Questa è la mia soluzione preferita quando ricevo OutOfMemoryError in Eclipse, Maven o ANT durante la creazione del progetto perché in base alle dimensioni del progetto puoi facilmente esaurire la memoria.

Ecco un esempio di aumento della dimensione massima dell'heap di JVM. Inoltre è meglio mantenere la proporzione da -Xmx a -Xms 1:1 o 1:1,5 se stai impostando la dimensione dell'heap nella tua applicazione Java.

export JVM_ARGS="-Xms1024m -Xmx1024m"

Collegamento di riferimento

Per impostazione predefinita, per lo sviluppo JVM utilizza dimensioni ridotte e configurazione ridotta per altre funzionalità relative alle prestazioni.Ma per la produzione puoi ottimizzare ad es.(Inoltre può esistere una configurazione specifica del server delle applicazioni) -> (Se non c'è ancora memoria sufficiente per soddisfare la richiesta e l'heap ha già raggiunto la dimensione massima, si verificherà un OutOfMemoryError)

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        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)

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

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 questi parametri 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

Tieni presente che la JVM utilizza più memoria del semplice heap.Ad esempio, i metodi Java, gli stack di thread e le maniglie native sono allocati in memoria separati dal heap, nonché strutture di dati interni JVM.

Ho affrontato lo stesso problema dalla dimensione dell'heap Java.

Ho due soluzioni se stai usando Java 5 (1.5).

  1. installa semplicemente 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 qualunque sia.Basta aggiungere una riga sotto di tutti gli argomenti presenti negli argomenti VM come -xms512m -xmx512m -xx: maxpermesze = ... m (192m).

Penso che funzionerà...

Ho letto da qualche altra parte che puoi provare: cattura java.lang.OutOfMemoryError e sul blocco catch, puoi liberare tutte le risorse che sai potrebbero utilizzare molta memoria, chiudere connessioni e così via, quindi eseguire un System.gc() quindi riprova quello che stavi per fare.

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

L'idea è di eseguire la Garbage Collection chiamando System.gc() che è noto per aumentare la memoria libera.Puoi continuare a controllarlo dopo l'esecuzione di un codice che consuma memoria.

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

Se è necessario monitorare l'utilizzo della memoria in fase di esecuzione, il file java.lang.management offerte di pacchetti MBeans che può essere utilizzato per monitorare i pool di memoria nella tua VM (ad esempio, Eden Space, Tenered Generation, ecc.) e anche il comportamento di garbage collection.

Lo spazio heap libero riportato da questi MBean varierà notevolmente a seconda del comportamento GC, in particolare se l'applicazione genera molti oggetti che vengono successivamente elaborati in GC.Un approccio possibile consiste nel monitorare lo spazio heap libero dopo ogni GC completo, che potresti essere in grado di utilizzare per prendere una decisione sulla liberazione della memoria mediante la persistenza degli oggetti.

In definitiva, la soluzione migliore è limitare il più possibile la conservazione della memoria mentre le prestazioni rimangono accettabili.Come notato in un commento precedente, la memoria è sempre limitata, ma la tua app dovrebbe avere una strategia per gestire l'esaurimento della memoria.

Tieni presente che se ne hai bisogno in una situazione di distribuzione, considera l'utilizzo di Java WebStart (con una versione "ondisk", non quella di rete - possibile in Java 6u10 e versioni successive) in quanto consente di specificare i vari argomenti della JVM in una croce modo della piattaforma.

Altrimenti avrai bisogno di un launcher specifico per il sistema operativo che imposti gli argomenti di cui hai bisogno.

Se questo problema si verifica in Wildfly 8 e JDK1.8, dobbiamo specificare le impostazioni MaxMetaSpace anziché le impostazioni PermGen.

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

Per ulteriori informazioni, consultare Problema dell'heap Wildfly

Per quanto riguarda netbeans, è possibile impostare la dimensione massima dell'heap per risolvere il problema.

Vai su 'Esegui', quindi --> 'Imposta configurazione progetto' --> 'Personalizza' --> 'esegui' della finestra visualizzata --> 'Opzione VM' --> compila '-Xms2048m -Xmx2048m' .

Se continui ad allocare e mantenere i riferimenti all'oggetto, riempirai tutta la quantità di memoria che hai.

Un'opzione è quella di chiudere e aprire un file trasparente quando cambiano scheda (mantieni solo un puntatore al file e quando l'utente cambia scheda, chiudi e pulisci tutti gli oggetti...renderà la modifica del file più lenta...ma...), e magari tenere 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 (poiché non è possibile aprire il file) chiudere quel file, pulire i suoi oggetti e avvisare l'utente che dovrebbe chiuderlo inutilizzato File.

La tua idea di estendere dinamicamente la memoria virtuale non risolve il problema, poiché la macchina ha risorse limitate, quindi dovresti stare attento e gestire i problemi di memoria (o almeno stare attento con loro).

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

--> Tieni presente che se inserisci qualcosa in una raccolta e poi te ne dimentichi, hai ancora un forte riferimento ad essa, quindi annulla la raccolta, puliscila o fai qualcosa con essa...in caso contrario troverai una perdita di memoria difficile da trovare.

--> Forse, usare raccolte con riferimenti deboli (weakhashmap...) può aiutare con problemi di memoria, ma tu dovere fai attenzione, perché potresti scoprire che l'oggetto che cerchi è stato raccolto.

--> Un'altra idea che ho trovato è quella di sviluppare una raccolta persistente memorizzata sugli oggetti del database meno utilizzati e caricati in modo trasparente.Questo probabilmente sarebbe l'approccio migliore...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top