2013-12-17 19 views
21

Sto esaminando una potenziale perdita di memoria (o almeno uno spreco di memoria) in un sistema basato su Java di dimensioni maggiori. La JVM è in esecuzione con una dimensione heap massima di 5 GB e l'utilizzo di heap di 2-3 GB è una linea di base prevista per l'applicazione. (Possono esserci picchi più alti)Ricerca di perdite di memoria Java quando non tutti gli heap utilizzati sono raggiungibili dai thread

In uno scenario di sovraccarico che sto esaminando, l'heap viene riempito. Analizzando un heap-dump con "Eclipse MemoryAnalyzer Tool" viene mostrato (non sorprende) che l'heap sia interamente esaurito.

MAT mostra 2 potenziali candidati alla perdita, entrambi con una tolleranza di 2,5 GB: java.lang.Thread e un oggetto dominio dal sistema che viene ampiamente utilizzato durante l'elaborazione delle transazioni nel sistema. Tuttavia, tutti questi oggetti di dominio sono (non a sorpresa) raggiungibili dalle istanze di Thread. Quei thread stanno elaborando le transazioni, dopo tutto. Pertanto, i 2.5 GB attribuiti a java.lang.Thread sono quasi interamente causati da tali oggetti di dominio. Nessuna sorpresa qui.

Elencare la struttura ad albero di tutte le istanze java.lang.Thread e sommare l'heap mantenuto di tutti i thread risulta in 2,5 GB di heap conservato.

Dove devo cercare gli altri 2,5 GB necessari per riempire l'heap, se non sono raggiungibili da un'istanza di java.lang.Thread? - Non c'è nulla in coda finalizzatore - Non è presente una notevole quantità di oggetti irraggiungibili in attesa GC

Penso che un altro modo per mettere questa domanda è: "Come faccio a trovare tutti gli oggetti che non sono raggiungibili da un'istanza di java.lang.Thread? Forse una query OQL ?, e l'altra domanda: "Che tipo di oggetti ci sono che non sono raggiungibili da un'istanza di java.lang.Thread altro da Oggetti nella coda di Finalizer e oggetti non referenziati in attesa di GC ? "

+0

Ti dispiacerebbe fornire altri dati. Come forse il grafico di cui stai parlando e gli oggetti Dominio stessi. Come sono usati Fanno un grande uso di matrici di dimensioni strane? C'è un'assegnazione che fallisce e provoca il lancio di una OOM? –

+0

Si prega di includere anche se si stanno utilizzando o meno flag GC (come: -XX: + CMSClassUnloadingEnabled -XX: + CMSPermGenSweepingEnabled -XX: + UseConcMarkSweepGC) – JoeG

+0

Sei sicuro che il 2.5 GB del thread includa anche gli oggetti del dominio? Se sono due conteggi separati, allora sarà pari al tuo 5GB. –

risposta

4

anch'io affrontato il problema con le perdite di memoria sul nostro sito,
Usa yourkit java profiler che forniscono un sacco di informazioni e con la sua capacità si può avere un'immagine più ampia in cui è utilizzata tutta la memoria.
È possibile trovare un ottimo tutorial Find Java Memory Leaks con lo strumento sopra.

tua domanda,

"Che tipo di oggetti ci che non sono raggiungibili da un'istanza di java.lang.Thread altri poi oggetti in Finalizer coda e gli oggetti non referenziati in attesa GC sono?"

Ci sono quattro tipi di oggetto,

  1. Strong raggiungibile, oggetti che possono essere raggiunte direttamente tramite riferimenti dagli oggetti vivi
  2. deboli/molli raggiungibili, oggetti che stanno avendo debole/riferimento molle associato con loro
  3. Finalizzazione in attesa, oggetti in sospeso per la finalizzazione e il cui riferimento può essere raggiunto tramite la coda di finalizzazione
  4. Non raggiungibili questi sono oggetti irraggiungibili f ROM radici GC, ma non ancora incassati

Oltre a questi JVM usa anche la memoria dei nativi le cui informazioni si possono trovare su IBM Heap and native memory use by the JVM e Thanks for the memory e secondo YourKit il JVM Memory Structure ha non-memoria heap cui definizione secondo loro è

Inoltre, la JVM ha una memoria diversa dall'heap, definita memoria non heap. Viene creato all'avvio di JVM e memorizza strutture per classe come pool di costanti di runtime, dati di campi e metodi e il codice per metodi e costruttori, nonché stringhe internate.

+1

, la JVM non rimuove i riferimenti Weak/Soft prima di lanciare un errore OutOfMemory in un ultimo disperato tentativo di liberare carica più memoria possibile? – dkatzel

+1

sì è vero che JVM proverà a liberare tutta la memoria possibile prima di lanciare l'eccezione "OutOfMemory' ma questo non è correlato alla domanda e anch'io non ho menzionato nessuno – dbw

+1

controllerò il tuo kit – VoidPointer

0

Forse dovresti cercare perdite di memoria nel codice del connettore del database o forse ORM .Perché se stai usando una libreria di connessione grezza quando non chiudi il cursore puoi ottenere potenzialmente perdite di memoria. a connettore del database. Perché alcuni di essi (potrebbero non essere i tuoi) utilizzano il codice nativo sottostante e questa è la fonte di questa perdita. A causa del pesante uso concomitante che rende sensuale per me. Puoi verificarlo se vuoi.

3

Poiché la memoria aggiuntiva non viene visualizzata in MAT, è difficile sapere cosa suggerire. Le mie scuse se alcune (o anche la maggior parte) di ciò sono cose che già sapete, ho appena provato a mettere insieme tutto quello che potevo pensare.

FindBugs

FindBugs è uno strumento di analisi statica che esegue la scansione il codice alla ricerca di anti-pattern e problemi comuni e dando una bella relazione di accompagnamento. Raccoglie un sacco di cause di potenziali perdite di memoria e risorse.

discarica Manuale

Si potrebbe provare a utilizzare qualcosa come jmap o VisualVM di prendere un heap dump per l'analisi manualmente e vedere se si ottengono risultati diversi da lasciare eclissi lo fanno:

http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jmap.html

http://java.dzone.com/articles/java-heap-dump-are-you-task

Analyzer Quirks

L'analizzatore di memoria FAQ:

http://wiki.eclipse.org/MemoryAnalyzer/FAQ

dice:

Sintomo: Durante il monitoraggio l'utilizzo della memoria in modo interattivo, la dimensione heap utilizzato è molto più grande di quello che i rapporti MAT.

Durante la creazione dell'indice, l'Analizzatore di memoria rimuove gli oggetti non raggiungibili perché i vari algoritmi di garbage collector tendono a lasciare un po 'di spazzatura (se l'oggetto è troppo piccolo, spostare e riassegnare gli indirizzi è troppo costoso). Questo dovrebbe, tuttavia, non essere più del 3-4%. Se si desidera sapere quali oggetti vengono rimossi, abilitare l'output di debug come spiegato qui: MemoryAnalyzer/Domande frequenti # Enable_Debug_Output

Un altro motivo potrebbe essere che il dump dell'heap non è stato scritto correttamente. Specialmente VM meno recenti (1.4, 1.5) possono avere problemi se il dump dell'heap viene scritto tramite jmap.

Abilitare l'output di debug vi permetterà di vedere cosa sta succedendo lì e confermare che non c'è nulla di strano in quell'area.

Alcuni di questi suggerimenti possono essere rilevanti

http://eclipsesource.com/blogs/2013/01/21/10-tips-for-using-the-eclipse-memory-analyzer/

+1

Grazie, queste sono tutte cose molto buone da esplorare ... Almeno ho altre indicazioni per esplorare – VoidPointer

1

Usa JProfiler e rompere contare l'oggetto mucchio per classe - trovare quale classe ha un sacco di casi e avvia il caccia lì.

È inoltre possibile scattare un paio di istantanee a breve distanza e confrontare i due dump di heap per vedere quali oggetti sono stati creati durante tale periodo. Ciò è particolarmente utile se si sa che una determinata azione causa il problema e si desidera ignorare tutto il rumore degli oggetti JVM in background ed esaminare il delta.

L'ho usato con grande successo per trovare una perdita di memoria. Non è gratuito, ma vale la pena pagare la licenza.

FYI: Non ho alcuna affiliazione con JProfiler.

0

Since the extra memory is not showing in MAT it's hard to know what to suggest. Non è vero. MAT mostra oggetti non raggiungibili. Vai su de Preferenze e seleziona la casella di controllo che abilita questa opzione. Dopo il riavvio MAT vedrai questi oggetti con i dettagli. Naturalmente le radici di GC non saranno disponibili.

Problemi correlati