Domanda

Qual è il modo migliore per eseguire il debug eccezioni java.lang.OutOfMemoryError?

Quando questo accade alla nostra applicazione, il nostro application server (WebLogic) genera un file di dump heap. Dovremmo utilizzare il file heap dump? Dovremmo generare un dump thread Java? Che cosa è esattamente la differenza?


Aggiornamento: Qual è il modo migliore per generare discariche filo? kill -3 (nostre piste app su Solaris) è il modo migliore per uccidere l'applicazione e generare un dump filo? C'è un modo per generare il dump thread, ma non uccide l'applicazione?

È stato utile?

Soluzione

Analisi e fissaggio out-of-memoria errori in Java è molto semplice.

In Java gli oggetti che occupano memoria sono tutti collegati ad altri oggetti, formando un albero gigante. L'idea è quella di trovare le più grandi rami dell'albero, che di solito puntare ad una situazione di perdita di memoria (in Java, non è perdita di memoria quando si dimentica di eliminare un oggetto, ma quando ci si dimentica di dimenticare l'oggetto, vale a dire a mantenere un riferimento ad esso da qualche parte).

Passaggio 1. Attivare mucchio discariche in fase di esecuzione

Esegui il processo con -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp

(E 'sicuro di avere queste opzioni sempre abilitate. Regolare il percorso, se necessario, deve essere scrivibile dall'utente java)

Punto 2. riprodurre l'errore

Far funzionare applicazione finché non si verifica il OutOfMemoryError.

La JVM scriverà automaticamente un file come java_pid12345.hprof.

passaggio 3. Fetch discarica

Copia java_pid12345.hprof al PC (sarà almeno altrettanto grande come la vostra massima dimensione heap, quindi può diventare piuttosto grande - gzip se necessario)

.

Passaggio 4. Aprire il file dump con IBM Heap Analyzer o Eclipse di Memory Analyzer

Il Mucchio analizzatore si presenterà con un albero di tutti gli oggetti che erano in vita al momento dell'errore. Le probabilità sono che vi punto direttamente il problema quando si apre.

IBM HeapAnalyzer

Nota: dare HeapAnalyzer memoria sufficiente, dal momento che deve caricare l'intera discarica

java -Xmx10g -jar ha456.jar

passaggio 5. Individuare le aree di più grande uso mucchio

Sfoglia attraverso l'albero di oggetti e di identificare gli oggetti che sono mantenuti intorno inutilmente.

Nota può anche accadere che tutti degli oggetti sono necessari, il che significherebbe avete bisogno di un mucchio più grande. Dimensioni e sintonizzare mucchio opportunamente .

Passo 6. Fissare il codice

Assicurati di solo mantenere gli oggetti in giro che è effettivamente necessario. Rimuovi elementi provenienti da collezioni in modo tempestivo. Assicurarsi di non tenere i riferimenti a oggetti che non sono più necessari, solo allora potranno essere garbage collection.

Altri suggerimenti

Ho avuto successo utilizzando una combinazione di Eclipse Memory Analyzer (MAT) e Java VM visiva per analizzare dump heap. MAT ha alcuni rapporti che è possibile eseguire che vi danno un'idea generale di dove concentrare i vostri sforzi all'interno del codice. VisualVM ha una migliore interfaccia (a mio parere) per realtà ispezionare il contenuto dei vari oggetti che si sono interessati ad esaminare. Ha un filtro in cui si può avere visualizzare tutte le istanze di una particolare classe e vedere dove ne viene richiesto e ciò che essi stessi di riferimento. E 'stato un po' che ho usato uno dei due strumenti per questo possono avere un set di funzionalità più vicino adesso. Al momento utilizzando sia funzionato bene per me.

In genere è molto difficile eseguire il debug problemi OutOfMemoryError. Mi consiglia di utilizzare uno strumento di profiling. JProfiler funziona piuttosto bene. L'ho usato in passato e può essere molto utile, ma sono sicuro che ci sono altri che sono almeno altrettanto buono.

Per rispondere alle vostre domande specifiche:

Un mucchio discarica è una visione completa di tutto il mucchio, vale a dire tutti gli oggetti che sono stati creati con new. Se siete a corto di memoria, allora questo sarà piuttosto grande. Esso mostra il numero di ogni tipo di oggetto che avete.

una discarica filo mostra la pila per ogni thread, che vi mostra dove nel codice ogni thread è al momento del dump. Ricorda che qualsiasi thread potrebbe aver causato la JVM per esaurire la memoria ma potrebbe essere un thread diverso che in realtà genera l'errore. Per esempio fili 1 alloca un array di byte che riempie tutto lo spazio disponibile mucchio, quindi infilare 2 tenta di allocare una matrice di 1 byte e genera un errore.

È inoltre possibile utilizzare jmap / jhat per connettersi a un processo Java in esecuzione. Questi (famiglia di strumenti) sono davvero utili se si deve eseguire il debug di un'applicazione in esecuzione dal vivo.

Si può anche lasciare jmap esecuzione come la registrazione compito cron in un file che è possibile analizzare in seguito (E 'qualcosa che abbiamo trovato utile per eseguire il debug di una perdita di memoria dal vivo)

jmap -histo:live <pid> | head -n <top N things to look for> > <output.log>

jmap può anche essere usato per generare un heap dump utilizzando l'opzione -dump che può essere letta attraverso il jhat.

Vedere il seguente link per maggiori dettagli http: //www.lshift .net / blog / 2006/03/08 / java-memory-profiling-con-jmap-e-jhat

Ecco un altro link per segnalare http://java.sun.com/developer/technicalArticles/J2SE/monitoring/

Qual è il modo migliore per eseguire il debug eccezioni java.lang.OutOfMemoryError?

Il OutOfMemoryError descrive tipo di errore nella descrizione del messaggio. È necessario controllare la descrizione del messaggio di errore per gestire l'eccezione.

Ci sono varie cause alla radice di fuori delle eccezioni di memoria. Fare riferimento alla documentazione di Oracle pagina per maggiori dettagli .

java.lang.OutOfMemoryError: Java heap space:

Causa :. Il particolare spazio messaggio Java heap indica oggetto non poteva essere allocata nel mucchio Java

java.lang.OutOfMemoryError: GC Overhead limit exceeded:

Causa: Il messaggio dettaglio "GC limite sovraccarico superato" indica che il garbage collector è in esecuzione tutto il tempo e programma Java sta compiendo progressi molto lenti

java.lang.OutOfMemoryError: Requested array size exceeds VM limit:

Causa : Il messaggio dettaglio "dimensione dell'array desiderata supera il limite VM" indica che l'applicazione (o API utilizzate da tale applicazione) tentato di allocare una matrice che è più grande della dimensione heap

java.lang.OutOfMemoryError: Metaspace:

Causa: Java classe di metadati (le macchine virtuali presentazione interna della classe Java) è allocato in memoria nativa (di cui qui come metaspace)

java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?:

Causa: Il dettaglio messaggio "dimensione della richiesta di byte per ragioni di spazio di swap.?" sembra essere un'eccezione OutOfMemoryError. Tuttavia, il codice Java HotSpot VM segnala questa eccezione evidente quando uno stanziamento dal mucchio nativa non è riuscita e il cumulo nativo potrebbe essere prossimo all'esaurimento

java.lang.OutOfMemoryError: Compressed class space

Causa: Su piattaforme a 64 bit un puntatore ai metadati classe può essere rappresentato da un offset (con UseCompressedOops) a 32 bit. Questo è controllato dai UseCompressedClassPointers bandiera riga di comando (per impostazione predefinita).

Se si utilizza il UseCompressedClassPointers, la quantità di spazio disponibile per i metadati di classe è fissato al valore CompressedClassSpaceSize. Se lo spazio necessario per UseCompressedClassPointers supera CompressedClassSpaceSize, è gettato un java.lang.OutOfMemoryError con il particolare compressa spazio di classe.

Nota: C'è più di un tipo di classe di metadati - Klass metadati e altri metadati. Solo i metadati Klass è memorizzato nello spazio delimitato da CompressedClassSpaceSize. L'altro metadati è memorizzato in Metaspace.

Dovremmo usare il file heap dump? Dovremmo generare un dump thread Java? Che cosa è esattamente la differenza?

Sì. È possibile utilizzare questo file heap dump heap per il debug del problema utilizzando strumenti di profiling come VisualVM o mat È possibile utilizzare discarica discussione per ottenere una visione più completa sullo stato di fili.

Fare riferimento a questa domanda SE conoscere i differenes:

Differenza tra javacore, discarica filo e heap dump in WebSphere

Qual è il modo migliore per generare discariche filo? È uccidere -3 (nostre piste app su Solaris) il modo migliore per uccidere l'applicazione e generare un dump filo? C'è un modo per generare la discarica filo, ma non uccidere l'app?

kill -3 <process_id> genera discarica Discussione e questo comando non uccide processo Java.

Una volta che si ottiene uno strumento per guardare al heap dump, un'occhiata a qualsiasi filo che era in stato di esecuzione nello stack di thread. La sua probabilmente uno di quelli che ha ottenuto l'errore. A volte l'heap dump vi dirà che cosa filo aveva il diritto errore nella parte superiore.

Questo dovrebbe puntare nella giusta direzione. Poi impiegare tecniche di debug standard (registrazione, debugger, ecc) per perfezionare in problema. Utilizzare la classe runtime per ottenere l'utilizzo della memoria corrente e accedere come il metodo o processo in questione esegue.

Io in genere uso Eclipse Memory Analyzer. Esso mostra i colpevoli presunti (gli oggetti che stanno occupando la maggior parte del heap dump) e diverse gerarchie di chiamata che sta generando tali oggetti. Una volta che la mappatura è lì possiamo tornare al codice e cercare di capire se c'è qualche possibile perdita di memoria in ogni dove il percorso di codice.

Tuttavia, OOM non sempre significa che v'è una perdita di memoria. È sempre possibile che la memoria necessaria per un'applicazione durante lo stato stabile o sotto carico non è disponibile nell'hardware / VM. Ad esempio, ci potrebbe essere un processo Java a 32 bit (memoria massima utilizzata ~ 4GB), dove come la VM ha appena 3 GB. In tal caso, inizialmente l'applicazione può funzionare bene, ma OOM può essere verificato come e quando il requisito di memoria si avvicina 3GB.

Come detto da altri, catturando discarica filo non è costoso, ma catturando heap dump è. Ho osservato che durante l'acquisizione di applicazione heap dump (in genere) si blocca e solo un kill seguito da riavvio aiuta a recuperare.

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