Hardware- und Softwareentwicklung, Java

Was tun bei OutOfMemory – Teil 2: Analyse

Nicht selten kommt es vor, dass Speicherprobleme erst im Wirkbetrieb auftreten. Die Gründe dafür sind oft, dass das System nicht ausreichend oder gar nicht unter realen Lastbedingungen getestet wurde.
Bei Systemen mit redaktionellen Inhalten (z. B. Content Management Systeme) ergibt sich aus der steigenden Anzahl der Inhalte in Verbindung mit Abhängigkeiten und Caching  eine wachsende Belastung. In der Testphase sind diese Inhalte in der Komplexität und Masse meist noch nicht verfügbar.

Wie bei vielen anderen Problemen auch, kann man OutOfMemory in zwei Kategorien einteilen:

  • Problem tritt regelmäßig auf:  Das Problem tritt immer nach gewisser Zeit oder beim Aufruf gewisser Methoden auf. Diese Art von Fehler ist meist gut nachstellbar und im Algemeinen auch schnell behoben. Die Ursache sind meist Programmierfehler.
  • Problem tritt sporadisch auf: Das Problem tritt immer mal wieder auf. Davor und danach läuft das System  weitergehend stabil. Hier ist extrem schwierig den Fehler nachzustellen und die Ursachen dafür einzugrenzen. Man sucht hier wortwörtlich die Nadel im Heuhaufen.

Geraden für den Typ 2 ist ein strukturiertes Vorgehen von großer Bedeutung. Es empfiehlt sich, ein Vorgehensmodel zu definieren und zu dokumentieren. Bei neuen Erkenntnissen wird das Vorgehensmodel erweitert oder ggf. angepasst. Für jeden Vorgehensschritt gibt es eine konkrete Aufgabe, die verschiedene Ergebnisse liefert. Dieses Vorgehen hat mehrere Vorteile:

  • Es gibt einen roten Faden: Die Komplexität ist meist sehr hoch. Wenn man nicht strukturiert die Probleme angeht, läuft man Gefahr, sich zu verzetteln.
  • Das Wissen kann besser auf mehrere Mitarbeiter verteilt werden: Sollte ein Mitarbeiter mal ausfallen (wegen Krankheit oder Urlaub) können andere Mitarbeiter diese Aufgabe übernehmen.
  • Es gibt Material für das Management: Das Management kann sich oft nicht vorstellen, warum es so lange dauert, das Problem zu lösen. Über das Vorgehensmodel ist geklärt, wo wir uns befinden, und was die nächsten Schritte sind. Über Entscheidungsvorlagen können weitere Budgets oder Termine abgestimmt werden.

Hilfreich ist es auch, Probleme und Teilerfolge im Team zu diskutieren. Dazu müssen Vorgehen und Ergebnisse auch in entsprechender Form aufbereitet werden.

Betriebskennzahlen ermitteln

Prozess und Speicher

Im Teil 1 wurde bereits dargestellt, dass die Größe des maximalen Speichers für einen Prozess abhängig von dem Betriebssystem und der Hardware ist.
Anzeigen kann man den Speicher für einen Prozess unter Linux mit dem Kommando top.

top -p <PID>

Weiterhin kann auch festgestellt werden, wie viel Ressourcen überhaupt noch zur Verfügung stehen.
Um herauszufinden, wie viel Speicher ein Prozess maximal einnehmen kann, benötigt man die genaue Kernel-Version und die Spezifikation des Betriebssystems.

uname -r (Linux)

Red Hat Enterprise Linux 4 includes a kernel known as the hugemem kernel.
This kernel supports a 4GB per-process user space (versus 3GB for the other kernels), and a 4GB direct kernel space.

Java-Speicherverlauf überwachen

  • GC-Logging aktivieren
JAVA_VM_ARGS="$JAVA_VM_ARGS -verbose:gc -Xloggc:var/logs/gc.log \
   -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC \
   -XX:+PrintTenuringDistribution"
  • Auswerten der Datei var/logs/gc.log mit dem Tool HPjtune

  • Kurz vor OutOfMemorykann durch GC kaum noch Speicher freigegeben werde
  • das Systen ist praktisch nur noch mit GC beschäftigt

Tomcat-Monitoring
Über die Tomcat-Manager-Seiten kann der Tomcat überwacht werden. Dafür muss ein Nutzer mit der Rolle manager in der Datei tomcat-users.xml existieren.

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
...
<role rolename="admin"/>
<role rolename="manager"/>
<user username="admin" password="admin" roles="admin, manager"/>
...
</tomcat-users>

Tomcat Monitoring URL: http://HOST:PORT/manager/status?XML=true

<?xml version="1.0" encoding="utf-8"?>
<status>
<jvm>
<memory free='206.306.536' total='424.214.528' max='492.175.360'/>
</jvm>
...
</status>

Grafisch ausgewertet werden können die Werte mit JMeter:

Speicherdumps auswerten

Oft findet man die Ursachen des Speicherproblems aber nur mit der Auswertung des Heapdumps. Zuerst muss man ein Heapdump erstellen. Es empfiehlt sich, den Heap für die Analyse nicht zu groß zu wählen. Eine Analyse eines 2 GB Dumps ist schon sehr schwierig.

  • Histogramm
     $JAVA_HOME/bin/jmap -histo <PID> > hist.txt
  • Binary HeapDump (komplett)
    $JAVA_HOME/bin/jmap -heap:format=b <PID>
  • Auswerten mit JHat (JDK 1.6)
    java -Xmx2048m -jar hat.jar ../java_pid27280.hprof
    Started HTTP server on port 7000
     Reading from ../java_pid27280.hprof...
     Dump file created Tue Nov 20 14:22:07 CET 2007

    die Auswertung kann dann webbasiert per Browser auf Port: 7000 erfolgen

  • Auswerten mit dem SAP Memory Analyzer
    • kostenloses Tool zum Analysieren von großen Memory Dumps
    • sehr schnelle (durch Indizierung)
    • sehr gute Analysemöglichkeiten
    • Bearbeitung großer Dumps
    • als Eclipse Plugin oder eigenständige Applikation (RPC-Framework)
    • Artikel im JavaMagazin (11/2007 S.105)
    • Download: https://wiki.sdn.sap.com/wiki/display/Java/Java+Memory+Analysis

 

Im gezeigten Beispiel war das Problem die Klasse BodyContentImpl des Tomcats (5) allerdings durch fehlerhafte Benutzung in einer eigenen Tag Library.

Links

Share on FacebookTweet about this on TwitterPin on Pinterest