1. jmap: Kommandozeilenmagie
Ein automatischer Garbage Collector ist natürlich großartig. Aber selbst Java-Anwendungen können Speicherlecks haben (OutOfMemoryError), langsam arbeiten oder unerwartet ausbremsen – wegen falscher Speichernutzung. Die Ursachen können unterschiedlich sein:
- Speicherlecks (memory leaks): Objekte, die hätten entfernt werden sollen, „leben“ weiter.
- Zu große Datenmengen in Collections.
- Fehler in der Caching-Logik.
- Nicht freigegebene Ressourcen (z. B. Threads, Dateien).
Ihre Aufgabe – solche Probleme schnell zu finden. Andernfalls laufen Sie Gefahr, nicht Programmierer, sondern „Bug-Entwickler“ zu werden!
Was ist jmap?
jmap ist ein Tool, das im Standardumfang des JDK enthalten ist. Es ermöglicht, ein „Abbild“ (heap dump) des Speichers eines laufenden Java-Prozesses zu erhalten. Dieses Abbild können Sie anschließend in anderen Werkzeugen öffnen und sehen, welche Objekte Speicher belegen, wie viele es sind und wer auf sie referenziert.
Heap-Dump – das ist wie ein Foto Ihres Heaps: alle darin befindlichen Objekte, ihre Typen, Verknüpfungen und Größen.
jmap verwenden
Ermitteln Sie die PID des Prozesses
Zu Beginn müssen Sie die Prozess-ID (PID) herausfinden, in der Ihre Java-Anwendung läuft. Das geht auf verschiedene Arten:
Über jps (ein weiteres Tool aus dem JDK):
jps -l
Sie sehen eine Liste der Java-Prozesse und ihrer PIDs.
Über den Task-Manager (Task Manager) oder ps unter Linux.
Erstellen Sie einen Heap-Dump
jmap -dump:format=b,file=heap.bin <PID>
- format=b – Binärformat (geeignet für die Analyse).
- file=heap.bin – Dateiname, in den der Dump gespeichert wird.
- <PID> – Prozess-ID.
Beispiel:
jmap -dump:format=b,file=heap.bin 12345
Was tun mit dem heap dump?
In der Regel wird der Dump in grafischen Tools analysiert (z. B. jvisualvm oder Eclipse MAT), denn Objekte manuell in einer Binärdatei zu suchen – das ist hohe Kunst und ein bisschen Masochismus.
Weitere Möglichkeiten von jmap
Speicherstatistik anzeigen:
jmap -heap <PID>
Zeigt Informationen über den Heap: Größe, verwendeter GC, Zustand.
Klassenliste:
jmap -histo <PID>
Zeigt Klassenstatistiken: wie viele Objekte welchen Typs, Gesamtgröße.
Beispielausgabe:
| # | Objekt | Anzahl | Bytes |
|---|---|---|---|
| 1 | |
1200 | 48000 |
| 2 | |
1000 | 32000 |
| 3 | |
200 | 12800 |
Das gibt bereits einen Eindruck: Wenn Sie plötzlich Millionen von Objekten eines Typs haben – gibt es Grund, nachzuforschen.
2. jvisualvm: visueller Speicheranalysator
jvisualvm ist ein grafisches Programm, das zum JDK gehört (sehen Sie im Ordner bin nach). Es ermöglicht, sich mit lokalen (und teilweise auch entfernten) Java-Prozessen zu verbinden, sie in Echtzeit zu überwachen, einen heap dump zu erstellen, Speicher-, Thread-, GC- und CPU-Statistiken anzusehen und sogar die Codeausführung zu profilieren.
Wenn Sie gern mit der Maus klicken und schöne Diagramme betrachten – ist das Ihr Werkzeug.
jvisualvm starten
In der Kommandozeile (oder über eine Verknüpfung unter Windows):
jvisualvm
Es öffnet sich ein Fenster, in dem Sie alle lokalen Java-Prozesse sehen.
Hauptfunktionen von jvisualvm
Speicherüberwachung in Echtzeit
- Wählen Sie den Prozess in der linken Liste aus.
- Wechseln Sie zum Tab Monitor.
- Sie sehen Diagramme zur Heap- und CPU-Auslastung sowie die Anzahl der Threads und Klassen.
Beispiel:

Heap Dump (Speicherabbild)
- Klicken Sie im Panel Monitor auf Heap Dump.
- Nach einigen Sekunden erscheint ein Tab mit der Dump-Analyse.
- Sie sehen eine Liste aller Klassen, die Anzahl der Objekte und ihre Gesamtgröße.
Suche nach „schweren“ Objekten
- Sortieren Sie nach Größe oder Anzahl.
- Wenn ein Typ (z. B. ArrayList oder String) zu viel Speicher belegt – ist das ein Anlass zur Untersuchung.
Referenzanalyse (Reference Graph)
- Klicken Sie auf eine Klasse – Sie sehen, wer auf Objekte dieses Typs referenziert.
- Sie können bis zur Wurzel „vordringen“: warum ein Objekt nicht vom Garbage Collector entfernt wird.
Thread-Analyse
- Der Tab Threads – zeigt alle Threads und ihren Zustand.
- Sie können „hängende“ oder zu aktive Threads erkennen.
Profiling
- Der Tab Profiler – misst, welche Methoden am meisten Zeit oder Speicher beanspruchen.
- Das ist bereits eine tiefgehende Analyse, aber für die Suche nach Speicherlecks reichen die ersten Schritte.
3. Praxis: ein Speicherleck analysieren
Beispielcode mit Leak
import java.util.ArrayList;
import java.util.List;
public class MemoryLeakDemo {
// Statische Sammlung – Klassiker!
private static final List<String> bigList = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 1_000_000; i++) {
bigList.add("Zeile Nummer " + i);
if (i % 100_000 == 0) {
System.out.println("Hinzugefügt: " + i);
Thread.sleep(500); // Zeit für die Analyse geben
}
}
System.out.println("Fertig! Schließen Sie die Anwendung nicht, öffnen Sie jvisualvm.");
Thread.sleep(600_000); // 10 Minuten – Zeit für die Analyse
}
}
Was passiert hier?
- Wir erstellen eine statische Liste und fügen eine Million Zeichenketten hinzu.
- Nach dem Hinzufügen „pausiert“ das Programm (wartet), damit Sie sich mit Analysewerkzeugen verbinden können.
Analyse mit jvisualvm
- Starten Sie das Programm.
- Öffnen Sie jvisualvm und wählen Sie den Prozess.
- Im Tab Monitor sehen Sie das Speicherdigramm.
- Wenn alles in Ordnung ist, sollte der Speicher nach dem GC „freigegeben“ werden.
- Wenn es ein Leak gibt, wächst der Speicher nur an.
- Erstellen Sie einen Heap-Dump.
- Prüfen Sie, welche Objekte am meisten Speicher belegen.
- In unserem Fall – java.util.ArrayList und java.lang.String.
- Klicken Sie auf ein Objekt – sehen Sie, wer darauf referenziert.
- Sie werden sehen, dass es das statische Feld bigList ist.
Wie beheben?
- Entfernen Sie unnötige Elemente aus Collections und begrenzen Sie deren Wachstum.
- Setzen Sie Referenzen auf schwere Objekte auf null, wenn sie nicht mehr benötigt werden.
- Halten Sie große Collections nicht in static, wenn sie nicht dauerhaft benötigt werden.
4. Weitere Werkzeuge: Eclipse MAT, jconsole
Eclipse Memory Analyzer (MAT)
Eclipse MAT ist ein kostenloses, aber leistungsfähiges Werkzeug zur Analyse von heap dump. Damit sehen Sie, welche Objekte Speicher belegen und welche andere festhalten – der sogenannte retained set. Das ermöglicht, exakt zu bestimmen, wo sich das Leak verbirgt.
Das Tool kann detaillierte Berichte über verdächtige Objekte (leak suspects) erstellen und kommt auch mit riesigen Dumps von mehreren Gigabyte problemlos zurecht.
Die Arbeit ist einfach: Sie erstellen einen Speicherdump mit jmap oder jvisualvm, öffnen ihn in MAT, klicken auf Leak Suspects Report – und erhalten einen fertigen Bericht, in dem potenzielle Probleme bereits hervorgehoben sind.
jconsole
jconsole ist ein einfaches und praktisches Tool zur Beobachtung der JVM in Echtzeit. Es zeigt, wie viel Speicher genutzt wird, wie stark die CPU ausgelastet ist, wie viele Threads laufen und wie sich der Garbage Collector verhält.
Im Unterschied zu fortgeschritteneren Werkzeugen wie VisualVM analysiert jconsole keinen heap dump, eignet sich jedoch hervorragend für eine schnelle Diagnose – wenn Sie auf einen Blick verstehen müssen, was gerade in der Anwendung passiert.
5. Typische Fehler bei der Speicheranalyse
Fehler Nr. 1: Sie erstellen den Dump des falschen Prozesses. Auf einer Maschine laufen oft viele Java-Anwendungen, da kann man PIDs verwechseln. Prüfen Sie über jps und stellen Sie sicher, dass Sie genau Ihr Programm analysieren.
Fehler Nr. 2: Sie erwarten ein „Leak“, wo es keines gibt. Der GC entfernt Objekte nicht immer sofort – manchmal wird Speicher erst nach einem Full GC freigegeben. Keine Panik, wenn nach einer Iteration der Speicher nicht freigegeben wurde – betrachten Sie den Trend.
Fehler Nr. 3: Sie berücksichtigen den Einfluss statischer/gecachter Objekte nicht. Viele Lecks hängen damit zusammen, dass Objekte in static-Feldern oder globalen Collections gespeichert sind. Prüfen Sie, wer auf „schwere“ Objekte referenziert – oft ist es static.
Fehler Nr. 4: Sie verwenden kein Profiling in der Dynamik. Heap dump ist gut, aber manchmal ist es wichtig, das Speicherwachstum über die Zeit zu betrachten (Diagramme in jvisualvm). Wenn der Speicher stabil wächst – gibt es Anlass zur Untersuchung.
Fehler Nr. 5: Sie entfernen Listener/Event-Handler nicht. Wenn Sie ein Ereignis abonnieren, sich aber nicht abmelden – bleibt das Objekt im Speicher „am Leben“, selbst wenn Sie es nicht mehr verwenden.
Tipp: Keine Scheu vor Experimenten mit den Tools! Erstellen Sie Dumps, betrachten Sie Diagramme, klicken Sie auf Objekte – nur so lernen Sie, den Speicher Ihrer Anwendung zu „spüren“ und Probleme schnell zu finden.
GO TO FULL VERSION