0

Ich habe eine Handvoll Heap-Dumps, die ich analysiere, nachdem die JVM OutOfMemory Exceptions ausgelöst hat. Ich verwende Hotspot JDK 1.7 (64bit) auf einer Windows 2008R2-Plattform. Der Anwendungsserver ist ein JBoss 4.2.1GA, der über die Tanuki Java Service Wrapper gestartet wird.Java HeapDumps zeigen an, dass die verwendete Heap-Größe nach OutOfMemory-Ausnahmen 30% kleiner als die tatsächliche Heap-Definition ist.

Es mit den folgenden Argumenten gestartet:

wrapper.java.additional.2=-XX:MaxPermSize=256m 
wrapper.java.initmemory=1498 
wrapper.java.maxmemory=3000 
wrapper.java.additional.19=-XX:+HeapDumpOnOutOfMemoryError 

die Seite übersetzen:

-Xms1498m -Xmx3000m -XX: MaxPermSize = 256m -XX: + HeapDumpOnOutOfMemoryError

einige andere sind GC & JMX-Konfigurationsparameter.

Mein Problem ist, wenn ich einen Heap-Speicherauszug analysiere, der aufgrund einer OutOfMemoryException unter Verwendung der Eclipse Memory Analyzer erstellt wurde, ausnahmslos MAT zeigt mir Heap Größen von 2.3G oder 2.4G. Ich habe bereits die Option in MAT zu Keep Unreachable Objects aktiviert, so glaube ich nicht, dass MAT den Haufen trimmt.

java.lang.RuntimeException: java.lang.OutOfMemoryError: GC overhead limit exceeded 

oder

java.lang.OutOfMemoryError: Java heap space 

Zusammenfassung in MAT:

Size: 2.3 GB Classes: 21.7k Objects: 47.6m Class Loader: 5.2k 

Meine eigentlichen Haufen Dateigrößen sind ungefähr 3300KB, so dass sie im Einklang mit meiner 3000 m max Heap-Größe Einstellung.

Also wo ist die fehlende 500-600M Speicher in MAT? Warum zeigt MAT nur meine Heap-Größe als 2.4G an?

Andere Beiträge auf SO neigen dazu, anzuzeigen, dass es die JVM ist, einige GC vor dem Dumping der Heap zu tun, aber wenn die fehlenden 500M aufgrund eines GC ist, warum wirft es überhaupt die OOM an erster Stelle? Wenn ein GC tatsächlich 500M (oder fast 25% meines Heaps) aufräumen könnte, ist der JVM wirklich nicht genügend Arbeitsspeicher?

Gibt es Möglichkeiten, die Heap-Dumps zu optimieren, damit ich ein vollständiges/vollständiges Bild des Heap (einschließlich der fehlenden 500M) erhalten kann?

Wenn nicht, ich finde ich bin wirklich schwer zu finden, wie/warum ich auf diese OOMs in erster Linie stoße.

Wie von jemandem angefragt, binde ich die Ausgabe eines jstat -gc <PID> 1000 von einem Live-Knoten: http://pastebin.com/07KMG1tr.

+0

MAT druckt nur eine Nummer, die im Header der Heap-Dump-Datei gespeichert ist. Diese Zahl sagt nichts über die Vollständigkeit des Objektgraphen in der Dump-Datei aus. – Holger

Antwort

1

Welchen GC verwenden Sie? Du Eden wahrscheinlich fehlt, versuchen jstat - Java Virtual Machine Statistics Monitoring Tool

+0

Soweit ich das beurteilen kann, verwendet es den Standard-GC, der meines Wissens ParallelGC ist. –

+0

Können Sie bitte Ihre Jstat-Ausgabe teilen? – ebanouz

+0

Irgendwelche bestimmten Optionen/config, die ich für 'jstat' verwenden sollte, die Sie sehen möchten? –

1

java.lang.OutOfMemoryError: GC overhead limit exceeded

zu verwenden, bedeutet dies nicht unbedingt Ihr Haufen voll ist, siehe this Q&A

java.lang.OutOfMemoryError: Java heap space

und dies bedeutet nicht, dass Ihr Haufen hat 0 Byte links, es bedeutet, dass eine Zuteilungsanforderung nicht erfüllt werden konnte. Wenn etwas versucht, 600MB zuzuordnen, und es nur noch 500MB übrig sind, wird ein OOME geworfen.

If not, I find I'm really struggling to find how/why I'm encountering these OOMs in the first place.

Erhalten Sie einen Stack-Trace, um zu sehen, ob die Callsite, die die fragliche Zuweisung macht, irgendetwas verdächtig macht, wäre ein Anfang. Oder Sie könnten einfach versuchen, die Größe des Heapspeichers zu ändern, um zu sehen, ob das Problem verschwindet.

+0

Ich erkenne, dass das 'GC overhead limit überschritten 'bedeutet nicht, dass es voll ist, aber eher, dass es nicht genügend Speicherplatz zurückfordern kann. Es erscheint jedoch merkwürdig, dass diese Art von Ausnahme ausgelöst wird, wenn sie nicht zusätzlichen Speicherplatz zurückfordern muss. Und ich kann mir in Java keinen Weg vorstellen, einen 500MB Speicherblock in einem einzigen Anruf zu reservieren. Vielleicht mit einer anfänglichen Zuweisung zu einem Array oder Hashtable/etc mit einer massiven Größe, aber ansonsten kann ich mir nichts vorstellen, das diese Größe des Speicherblocks zuweisen würde. Fehle ich etwas Offensichtliches? –

Verwandte Themen