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.
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.
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.
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.
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.
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.
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.
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.