Analysieren von Speicherproblemen

Erfahren Sie, wie Sie die Ursache für Speicherprobleme mit Java-Anwendungen ermitteln. Sie können automatisch und manuell einen Heap-Dump und ein Heap-Histogramm generieren, um die Ursache zu identifizieren.

Beschreibung description

Umgebung

Experience Manager

Problem/Symptome

Die JAVA-Anwendung wird langsamer ausgeführt und schließlich ist der Speicher ausgegangen. Andernfalls wird in den Protokollen oder in der Konsolenausgabe ein Fehler angezeigt OutOfMemoryError: Java heap space oder OutOfMemoryError: gc overhead limit exceeded.

Auflösung resolution

Ursache
Solche Probleme können viele Ursachen haben.

Eine mögliche Ursache ist, dass die Java-Anwendung, in unserem Fall CRX / CQ von der Befehlszeile mit den standardmäßigen Heap-Speichereinstellungen von Java gestartet wurde. Das bedeutet, dass der jvm-Parameter -Xmx nicht angegeben wurde. CRX oder CQ benötigt mindestens 256 MB Heap, der für die Ausführung zugewiesen ist. Wenn dies das Problem ist, stellen Sie über die Befehlszeile sicher, dass die Heap-Speichereinstellungen festgelegt sind. Beispiel:

java -Xmx512m -jar *.jar

Ist dies nicht der Fall, kann Ihre Anwendung zu viele Objekte beibehalten, ohne sie für die Speicherbereinigung freizugeben. Dies wird als Speicherleck bezeichnet, weitere Informationen finden Sie hier. Informationen zur Analyse von Speicherproblemen in Java-Anwendungen finden Sie im folgenden Abschnitt.
Heap-Dump erstellen:

Generieren eines Heap-Dump automatisch

Um automatisch ein Heap-Dump zu erstellen, wenn nicht genügend Arbeitsspeicher zur Verfügung steht, können Sie den Parameter jvm hinzufügen -XX:+HeapDumpOnOutOfMemoryError , um automatisch einen Heap-Dump zu generieren, wenn die Anwendung einen OutOfMemoryError ausgibt. So wird beispielsweise

java -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -jar *.jar

Dadurch wird eine Heap-Dump-Datei (java_...hprof) im Arbeitsverzeichnis des Prozesses, sobald der Java-Prozess nicht genügend Arbeitsspeicher hat. Der Prozess kann nach der Erstellung des Heap-Dumps weiter ausgeführt werden. Normalerweise reicht eine Heap-Dump-Datei aus, um das Problem zu analysieren.

Hinweis:  Wenn Sie das crx-quickstart/server/start-Skript zum Starten Ihrer CRX-Instanz verwenden, können Sie -XX:+HeapDumpOnOutOfMemoryError zur Variable CQ_JVM_OPTS hinzufügen (stellen Sie sicher, dass die Variable auch unkommentiert ist). Beispiel:

CQ_JVM_OPTS='-XX:+HeapDumpOnOutOfMemoryError'

Nachdem Sie diesen Parameter hinzugefügt und die CRX-Instanz neu gestartet haben, überprüfen Sie, ob die neue jvm-Option festgelegt ist. Führen Sie ps -ef | grep java über die Befehlszeile aus. Überprüfen Sie dann, ob -XX:+HeapDumpOnOutOfMemoryError als Parameter des CRX-Java-Prozesses.

Wenn Sie aufgrund von Speicherplatzbeschränkungen ein anderes Verzeichnis für den Heap-Dump angeben müssen, können Sie den Parameter -XX:HeapDumpPath=/path/to/generate/heapdump hinzufügen, um dem jvm mitzuteilen, wo die Datei abgelegt werden soll.

Siehe here für eine Referenz zum Debugging verwandter jvm-Parameter.
Manuelles Generieren eines Heap-Dump
Sun/Oracle JVM

Um manuell einen Heap-Dump zu erzeugen, führen Sie diesen Befehl aus (jmap und jps befinden sich im Ordner bin Ihres jdk-Basis-Verzeichnisses):

  1. Suchen Sie nach der PID des Java-Prozesses, für den Sie eine Heap-Dump generieren.

    • In Unix oder Linux kann dies mit ps -ef | grep java oder jps -l
    • Unter Windows kann dies durch Öffnen des Aufgabenmanagers erfolgen, indem Sie die Taste drücken Ctrl+Shift+Esc Gehen Sie dann zu  Ansicht  Gehen Sie dann zu  Spalten auswählen Gehen Sie dann zu   PID (Process Identifier)  oder jps -l
  2. Führen Sie den untenstehenden jmap-Befehl unten aus, ersetzen Sie /path/to/generate/heapdumpfile.hprof durch den Speicherort, an dem Sie die Heap-Dump-Datei erzeugen möchten, und ersetzen Sie 1234 mit der PID, die Sie im vorherigen Schritt nachgeschlagen haben.

    code language-none
    jmap -dump:format=b,file=/path/to/generate/heapdumpfile.hprof 1234
    

IBM JVM

Sie müssen zunächst die standardmäßigen JVM-Einstellungen für die Dump-Agenten ändern, um die richtigen Dumps für das Benutzersignal zu erzeugen. Es gibt verschiedene Arten von Dumps, aber im Allgemeinen benötigen Sie einen vollständigen System-Dump, um eine gründliche Speicheranalyse durchzuführen. Fügen Sie die folgenden Argumente hinzu:

Xdump:heap:opts=PHD+CLASSIC:events=user -Xdump:system:events=user

Dieses "Benutzer"-Ereignis tritt auf, wenn die JVM das SIGQUIT-Signal (Linux, AIX®, z/OS® und i5/OS™) oder das SIGBREAK-Signal (Windows) vom Betriebssystem erhält.

Weitere Informationen finden Sie in der Dokumentation des Anbieters hier.

Warnung:  Heap-Dump-Dateien sind groß und können auf der Festplatte dieselbe Größe aufweisen wie Ihre maximale Heap -Xmx jvm-Parameterkonfiguration. Vergewissern Sie sich, dass dem Ordner, in dem die Dump-Datei generiert wird, genügend Speicherplatz zugewiesen ist.
Heap-Dump analysieren
Ein gutes Tool zur Analyse von Heap-Dumps ist EclipseMAT (Eclipse Memory Analyzer).

Dieses Tool kann keine mittels  IBM JVM  erzeugten Dumps analysieren. Für diese gibt es mehrere Möglichkeiten. IBM HeapAnalyzer eignet sich gut für Heap-Dumps im PHD- oder klassischen Format.

Verwenden Sie für eine vollständige Analyse des System-Dump den IBM Support Assistant Workbench, mit IBM Monitoring and Diagnostics Tools for Java - Memory Analyzer oben installiert. Das Heap-Histogramm ist eine einfache Messung der Anzahl der Live-Objekte und des Speichers, die pro Java-Klasse verwendet werden. Je nach Java-Installation sind die erforderlichen Tools leider nicht verfügbar oder funktionieren möglicherweise nicht immer. Um ein Heap-Histogramm zu erstellen, benötigen Sie zunächst die Prozess-ID des Java-Prozesses. Um es zu erhalten, führen Sie ps or (if available), run:Heap-Histogramm
Das Heap-Histogramm ist eine einfache Messung der Anzahl der Live-Objekte und des Speichers, die pro Java-Klasse verwendet werden. Je nach Java-Installation sind die erforderlichen Tools leider nicht verfügbar oder funktionieren möglicherweise nicht immer. Um ein Heap-Histogramm zu erstellen, benötigen Sie zunächst die Prozess-ID des Java-Prozesses. Um diese zu erhalten, führen Sie ps oder (falls verfügbar) Folgendes aus:

jps -l

Dieses Java-Tool ruft die Prozess-IDs aller ausgeführten Java-Prozesse ab. Beispiel:

327
3332 sun.tools.jps.Jps
3313 crx-quickstart-....jar

Führen Sie jetzt den folgenden Befehl aus:

jmap -histo 3313

Die Liste ist nach dem erforderlichen Gesamtspeicherbedarf sortiert (flach: referenzierte Objekte ausschließen). Die ersten 20 Zeilen der Ausgabe sind die interessantesten. Beispielausgabe:

JVM version is 1.5.0_20-141
Iterating over heap. This may take a while...
Warning: skipping invalid TLAB for thread t@62211
Warning: skipping invalid TLAB for thread t@62467
...
SizeCountClass description
-------------------------------------------------------
1059290412916byte`[` `]`
1028584075255* ConstMethodKlass
628317658388char`[` `]`
604230414928int`[` `]`
4995752116201* SymbolKlass
422089675255* MethodKlass
41965126969* ConstantPoolKlass
29285606969* InstanceKlassKlass
26310086066* ConstantPoolCacheKlass
2395872149742org.apache.jackrabbit.core.query.lucene.DocId$PlainDocId
14760087003java.util.HashMap$Entry`[` `]`
139612858172java.lang.String
107023244593java.util.HashMap$Entry
75398410036short`[` `]`
73546454org.apache.jackrabbit.core.query.lucene.DocId`[` `]`
7201927502java.lang.Class
64070413348com.day.crx.persistence.tar.index.IndexEntry
...

Weitere Informationen

Um das Problem analysieren zu können, müssen wir auch die folgenden Informationen kennen:

  • CRX- oder CQ-Version, einschließlich einer Liste aller installierten Hotfixes-Versionsnummern.
  • Betriebssystem, JVM-Anbieter und Version.

Verweise

[ 1] Oracle Help Center > Fehlerbehebungshandbuch für HotSpot VM
[ 2]  Oracle.com > javas > DebuggingOptions

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f