Layer 8Ehrlicher Tech-Support
SoftwareSchweregrad: Systemzerstörendjava.lang.OutOfMemoryError: Java heap space

OutOfMemoryError: Java heap space

Der Java-Prozess läuft gegen sein Speicherlimit. Mehr Heap zu geben ist oft nur ein Pflaster – meist steckt ein Speicherleck dahinter.

Aufwand:
ca. 60 Min.

Das Symptom

Die Anwendung läuft eine Weile, wird zäh, und bricht dann mit einem OutOfMemoryError: Java heap space ab. Nach einem Neustart läuft sie wieder – bis zum nächsten Mal. Der Abstand zwischen den Abstürzen wird mit der Zeit kürzer.

Die „Layer 8“-Wahrheit

„Dann geben wir ihr eben mehr Speicher.“ Dieser Satz beendet die Fehlersuche in den meisten Teams, und er ist fast immer falsch – erkennbar an genau einem Detail: Der Abstand zwischen den Abstürzen wird kürzer. Ein echter, legitimer Speicherbedarf wächst mit der Datenmenge, nicht mit der Laufzeit. Eine Anwendung, die nach jedem Neustart erneut vollläuft, hat kein Platzproblem. Sie hat ein Sammelproblem.

Java räumt Objekte automatisch weg, sobald niemand sie mehr braucht. Der Haken liegt in diesem „braucht“: Der Garbage Collector kann nicht wissen, was noch benötigt wird – er sieht nur, was noch referenziert wird. Eine Liste, die in einem statischen Feld hängt und der bei jeder Anfrage ein Eintrag hinzugefügt wird, den nie jemand entfernt, ist aus seiner Sicht bis zum letzten Byte in Gebrauch. Er räumt pflichtbewusst nichts davon weg, während der Speicher volläuft.

Deshalb ist der wichtigste Schritt nicht -Xmx, sondern ein Speicherabbild im Moment des Fehlers. Darin steht schwarz auf weiß, welche Objekte den Platz belegen und wer sie festhält. Alles andere ist raten – nur eben teurer.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Die Meldung genau lesen

    Java heap space heißt: Der Speicher für Objekte ist voll. Andere Varianten der Meldung, etwa zu Metaspace oder GC overhead, haben andere Ursachen. Der Zusatz hinter dem Doppelpunkt ist entscheidend.

  2. 2.

    Das aktuelle Limit kennen

    Die JVM nimmt sich nicht beliebig viel Speicher, sondern hält sich an ein Maximum. Ohne ausdrückliche Angabe leitet sie es vom verfügbaren Arbeitsspeicher ab – in einem Container von dessen Grenze, sofern die JVM aktuell genug ist.

  3. 3.

    Ein Speicherabbild anfordern

    Der entscheidende Schritt: Die JVM kann beim Fehler automatisch ein Speicherabbild schreiben. Darin steht, welche Objekte den Speicher belegen – und damit meist auch, wer das Leck verursacht.

    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/pfad/dump.hprof
  4. 4.

    Das Abbild analysieren

    Analysewerkzeuge zeigen die größten Objektgruppen und wer sie festhält. Wächst eine Sammlung unaufhörlich, weil Einträge hinzugefügt und nie entfernt werden, ist das Leck gefunden – und kein größerer Heap der Welt behebt es.

  5. 5.

    Erst danach den Heap vergrößern

    Ist der Speicherbedarf legitim, etwa weil die Datenmenge tatsächlich gewachsen ist, wird das Maximum angehoben. Vorher ist eine Vergrößerung nur eine Verlängerung der Frist bis zum nächsten Absturz.

    java -Xmx2g -jar anwendung.jar
  6. 6.

    Im Container die Grenzen abstimmen

    Läuft die Anwendung in einem Container, muss dessen Speicherlimit zum Heap passen. Ein Heap größer als das Containerlimit führt dazu, dass der Prozess hart beendet wird, bevor die JVM überhaupt eine Meldung ausgeben kann.

Häufige Fragen (FAQ)

?Reicht es nicht, einfach mehr Speicher zu geben?

Nur wenn der Bedarf echt ist. Bei einem Speicherleck verschiebt ein größerer Heap den Absturz lediglich nach hinten – aus einer Stunde werden drei. Das Leck wächst weiter, weil es nicht am Platz liegt, sondern daran, dass Objekte festgehalten werden, die niemand mehr braucht.

?Was ist der Unterschied zwischen Heap space und GC overhead limit exceeded?

Beim ersten ist der Speicher schlicht voll. Beim zweiten läuft die Speicherbereinigung dauernd, gewinnt aber kaum noch Platz zurück – die Anwendung verbringt fast ihre ganze Zeit mit Aufräumen. Beide zeigen dasselbe Grundproblem aus zwei Blickwinkeln.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWSystemzerstörendjava.lang.OutOfMemoryError: Metaspace

java.lang.OutOfMemoryError: Metaspace

Der Heap ist halb leer, die JVM stirbt trotzdem. Metaspace liegt im nativen Speicher und hat eine eigene Grenze – ein größerer Heap hilft nicht.

SWLästig

jcmd findet keine Java-Prozesse

jcmd -l listet nichts oder nur sich selbst, obwohl die JVM läuft. Schuld ist fast immer der falsche Benutzer – und sudo macht es schlimmer, nicht besser.

SWLästigUnsupportedClassVersionError

Java: UnsupportedClassVersionError

Das Programm wurde mit einem neueren Java kompiliert, als es ausführt? Diese Meldung nennt sogar die Versionsnummern — man muss sie nur übersetzen.