Speicherlecks erkennen und beheben
Erkennen und beheben Sie typische Muster für Speicherlecks, etwa statische Collections, Listener und Caches.
Speicherlecks erkennen und beheben ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was ist ein Memory Leak in Java?
Ein Memory Leak in Java tritt auf, wenn Objekte nicht mehr benötigt werden, aber weiterhin stark erreichbar sind und dadurch nicht von der GC freigegeben werden können. Der Heap wächst, bis ein OutOfMemoryError ausgelöst wird.
Ansammlung in statischen Collections
Ein statisches Feld, das eine wachsende Collection enthält, ist ein klassisches Leak. Hinzugefügte, aber nie entfernte Objekte bleiben für die gesamte Lebensdauer der Anwendung aktiv.
public class Cache {
// LEAK: static list grows forever if items are never removed
private static final List<Object> items = new ArrayList<>();
public static void add(Object o) { items.add(o); }
// Fix: add a remove() method or use a bounded cache
}Nicht abgemeldete Event-Listener
Wenn Sie einen Listener registrieren, ohne ihn jemals zu entfernen, bleiben sowohl der Listener als auch alle von ihm referenzierten Objekte aktiv. Melden Sie Listener immer ab, sobald sie nicht mehr benötigt werden.
// Leak:
sensor.addListener(new DataLogger());
// Fix:
DataLogger logger = new DataLogger();
sensor.addListener(logger);
// ... when done:
sensor.removeListener(logger);Nicht bereinigte ThreadLocal-Variablen
In Thread-Pools bleiben ThreadLocal-Werte zwischen Aufgaben erhalten, weil Threads wiederverwendet werden. Wenn sie nicht gelöscht werden, gelangen die Daten einer Aufgabe in nachfolgende Aufgaben desselben Threads.
private static final ThreadLocal<MyContext> CTX = new ThreadLocal<>();
// Always clean up after each task:
try {
CTX.set(new MyContext(requestId));
doWork();
} finally {
CTX.remove(); // prevents leak in pooled threads
}Classloader-Leaks in hot deployten Anwendungen
In Servlet-Containern verwendet jedes Deployment einen neuen Classloader. Wenn eine Klasse eine statische Referenz auf eine Klasse des alten Classloaders hält, können der gesamte alte Classloader und alle seine Klassen nicht von der GC eingesammelt werden.
Leaks mit Heap-Dumps erkennen
Erstellen Sie mit jmap -dump:format=b,file=heap.hprof <pid> einen Heap-Dump und öffnen Sie ihn anschließend in Eclipse MAT oder VisualVM, um die Objekte mit dem größten Retained Heap und deren GC Roots zu finden.
// Take a heap dump:
jmap -dump:live,format=b,file=heap.hprof $(jps | grep MyApp | cut -d" " -f1)
// Or trigger on OOM:
// -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap.hprofEclipse Memory Analyzer (MAT)
Der Bericht "Leak Suspects" von MAT identifiziert automatisch Objekte mit einem großen Retained Heap und zeigt den Pfad von den GC Roots. Beginnen Sie mit der Ansicht "Dominator Tree", um die größten Verursacher zu finden.
Leaks mit WeakReference vermeiden
Verpacken Sie Objekte aus Caches oder Listener in WeakReference. Der GC kann sie bei Speicherdruck freigeben. Prüfen Sie das Ergebnis von get() immer auf null.
Map<String, WeakReference<Image>> imageCache = new HashMap<>();
imageCache.put("logo", new WeakReference<>(loadImage("logo.png")));
Image logo = imageCache.get("logo") != null ? imageCache.get("logo").get() : null;
if (logo == null) logo = reload("logo.png"); // re-load if GCedBegrenzte Caches mit LinkedHashMap LRU
Überschreiben Sie removeEldestEntry in einer LinkedHashMap, um die Cache-Größe zu begrenzen und automatisch den am längsten nicht verwendeten Eintrag zu entfernen.
Map<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
protected boolean removeEldestEntry(Map.Entry<String, String> e) {
return size() > 100; // evict when over 100 entries
}
};Allokationen mit Java Flight Recorder profilen
JFR (Java Flight Recorder) erfasst Allokationsprofile mit minimalem Overhead. Aktivieren Sie es mit -XX:StartFlightRecording und analysieren Sie die Daten mit JDK Mission Control.
// Start a 60-second JFR recording:
java -XX:StartFlightRecording=duration=60s,filename=rec.jfr MyApp
// Or via jcmd:
jcmd <pid> JFR.start duration=60s filename=rec.jfrLeaks beheben: Checkliste
Prüfen Sie statische Collections, nicht registrierte Listener, ThreadLocals in Pools, Leaks bei Verbindungen und Streams (verwenden Sie try-with-resources), Referenzen innerer Klassen auf äußere Objekte sowie Caches ohne automatische Entfernung.
Schnelltest
Welches JVM-Flag erstellt automatisch einen Heap-Dump, wenn ein OutOfMemoryError ausgelöst wird?
Zusammenfassung
Häufige Quellen für Leaks in Java sind statische Collections, nicht registrierte Listener, ThreadLocals in Pools und unbegrenzte Caches. Erkennen Sie sie mit Heap-Dumps und MAT. Beheben Sie sie mit WeakReferences, begrenzten Datenstrukturen und indem Sie Referenzen immer entfernen, sobald sie nicht mehr benötigt werden.
Häufig gestellte Fragen
Ist die Lektion „Speicherlecks erkennen und beheben“ kostenlos?
Ja — der vollständige Text von „Speicherlecks erkennen und beheben“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Speicherlecks erkennen und beheben“?
Erkennen und beheben Sie typische Muster für Speicherlecks, etwa statische Collections, Listener und Caches. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Java Academy zu starten?
Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Speicherlecks erkennen und beheben“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?
Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- JVM-Heap-Bereiche und Objektlebenszyklus
- GC-Algorithmen: Serial, G1, ZGC, Shenandoah
- Speicherlecks erkennen und beheben
- GC-Tuning-Flags und JVisualVM-Profiling