Java OutOfMemoryError – Eine Tragödie in sieben Akten

2 Kommentare

Jeder Java Programmierer wird früher oder später über folgende Ausnahme stolpern: java.lang.OutOfMemoryError.

Mit ein wenig Glück passiert das noch während der Entwicklung. Tritt diese Ausnahme aber im produktiven Betrieb auf, erhält man schnell eine ungewollte Aufmerksamkeit im Management, da ein Java OutOfMemoryError in der Regel gleichbedeutend mit einem Produktionsausfall ist. Die Ursachen für diesen Fehler in der JVM sind vielfältig und nicht immer einfach zu analysieren. In der Praxis sehe ich täglich, dass Server jede Nacht neu gestartet werden um kontinuierlich anwachsendem Speicher Herr zu werden oder aber Anwendungen regelmäßig aus vermeindlich unerklärlichen Gründen ausfallen, auch wenn ein java.lang.OutOfMemoryError im Log darauf hin weist, dass der Hunger der Anwendung nach mehr Speicher einfach zu groß war.

Durch die Verbreitung von 64bit JVMs scheint für viele Anwendungen eine natürliche Lösung dieses Problems erschaffen worden zu sein: Mehr adressierbarer Speicher = Größere Java Heaps. Das Resultat ist dann häufig, dass der Java OutOfMemoryError meist deutlich später seinen großen Auftritt hat, aber dafür die Performance und der Durchsatz der Anwendungen unter dem erhöhten Verwaltungsaufwand der großen Heaps leiden. Sichtbar wird das durch hohe Pause-Zeiten des Garbage Collectors und eine überdurchschnittliche CPU Belastung durch den GC.

Obwohl Speicher Probleme nachweislich eines der größten Probleme von Java Anwendungen sind (fast 50% der Befragten unserer Performance Studie bestätigen das), findet man nur wenig nützliches über die Ursachen und Analyse von Java OutOfMemoryError. Mit dem notwendigen Hintergrundwissen, den richtigen Werkzeugen und einem methodischen Vorgehen kann man die meisten Speicher Probleme schnell finden und beheben. Diese Blog Serie wird sich daher genau mit diesen Themen beschäftigen und hoffentlich zu einer stabileren und performanteren Java Welt beitragen.

Die Serie habe ich „Java OutOfMemoryError – Eine Tragödie in sieben Akten“ getauft, weil mir ein Satz der Definition einer Tragödie auf Wikipedia sehr gut gefallen hat:

Im Kontext der Tragödie bedeutet „tragisch“ im Gegensatz zur Alltagssprache aber nicht, dass etwas sehr traurig ist, sondern dass jemand aus einer hohen Stellung „schuldlos schuldig“ wird und damit den Sturz über eine große „Fallhöhe“ erlebt.

Aus meiner Erfahrung werden die meisten Entwickler „schuldlos schuldig“, wenn Sie unwissentlich einen Java OutOfMemoryError in eine Anwendung eingebaut haben. In vielen Troubleshooting Einsätzen habe ich aber oft das Gefühl, dass man eher an Schuldigen als an den Ursachen des Problems interessiert ist – das ist dann doch eher „traurig“. Gerade deshalb finde ich es wichtig, dass man als Java Entwickler das notwendige Grundwissen erhält Speicher Probleme zu vermeiden und bei Bedarf schnell zu finden und zu eliminieren.

Hier die sieben Akte meiner Java Memory Tragödie im Überblick:

1. Akt – Das Java Memory Modell.

Im ersten Teil der Serie möchte ich die Architektur und den Aufbau des Speichers innerhalb einer JVM im Detail erklären und zeigen wann und wo java.lang.OutOfMemoryError auftreten können.

2. Akt – Java Memory Leaks und andere Übeltäter.

Der zweite Teil der Serie beschäftigt sich im Detail mit den Ursachen von java.lang.OutOfMemoryError – insbesondere mit Java Memory Leaks und zu hohem Speicherverbrauch in Java Anwendungen.

3. Akt – Konfiguration und Überwachung der Java Virtual Maschine.

Der dritte Teil der Serie zeigt, mit welchen Parametern man den Speicher einer JVM konfigurieren kann und welche Werkzeuge es gibt, um den Speicher zu überwachen. Da sich die JVM Implementierung der Hersteller stark unterscheiden, wird der Artikel sich auf die HotSpot Implementierung von Sun konzentrieren.

4. Akt – Java Heapdumps erzeugen und verstehen.

Der vierte Teil der Serie zeigt, wie man einen Heapdump zur Laufzeit und beim Ausfall einer JVM erzeugt und auswertet.

5. Akt – Java Heap Analyse zur Laufzeit.

Der fünfte Teil der Serie beschäftigt sich mit Werkzeugen und Vorgehensmodellen für die Laufzeitanalyse des Speichers von Java Anwendungen. Insbesondere wird hier das Thema hoher temporärer Speicherverbrauch und das Aufspüren von Memory Leaks behandelt.

6. Akt – Typische Java Memory Probleme

Der sechste Teil beschreibt typische OutOfMemoryError Szenarien an Hand von konkreten Beispielen und zeigt, wie man mit Hilfe des Wissens, der Werkzeuge und Methoden der Teile 1-5 der Serie, diese Probleme verstehen und veheben kann.

7. Akt – Zusammenfassung und Ausblick

Der letzte Teil fasst noch einmal final zusammen, was in der Serie behandelt wurde und gibt einen Ausblick auf den geplante Nachfolger dieser Tragödie: Java Garbage Collector – Das unbekannte Wesen.

Freue mich diese Serie in den nächsten Tagen und Wochen zu schreiben und hoffe, dass sie Euch hilft Java OutOfMemoryError Probleme besser zu verstehen. Im besten Fall könnt Ihr Sie dann vermeiden, aber zumindest solltet Ihr sie schnell finden und beheben können. Die einzelnen Akte dieser Tragödie könnt Ihr dann in den nächsten Tagen, Wochen und Monaten hier im Blog verfolgen.

Weitere Information zu diesem Thema liefern auch die Java Magazin Artikel von Alois Reitbauer und mir aus der Performance Antipatterns Serie, die Ihr bei uns auf der Webseite im Bereich „Artikel“ findet.

Autor

Mirko Novakovic

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Artikel von Mirko Novakovic

Konferenzen

APM Mythen Jäger entlarvt

Performance

Debunking the APM myth busters

Weitere Inhalte zu Allgemein

Kommentare

  • März 15, 2010 von Andrew

    Interesting Stuff…

    Looking forward to catching the others in the series

  • April 2, 2010 von Jens S.

    Hi Mirko,

    wirklich toller Text mit vielen guten Infos. Kannst du mir sagen wann die weiteren Teile folgen? :-)

    LG

    Jens

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *