0Pricing
Java Academy · Lesson

Detecting and Fixing Memory Leaks

Identify common memory leak patterns (static collections, listeners, caches) and fix them.

Detecting and Fixing Memory Leaks is a free Java Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Java Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Is a Memory Leak in Java?

A Java memory leak occurs when objects are no longer needed but remain strongly reachable, preventing GC from reclaiming them. The heap grows until an OutOfMemoryError is thrown.

Static Collection Accumulation

A static field holding a growing collection is a classic leak. Objects added but never removed stay alive for the lifetime of the application.

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
}

Unregistered Event Listeners

Registering a listener without ever removing it keeps both the listener and any objects it references alive. Always unregister listeners when they are no longer needed.

// Leak:
sensor.addListener(new DataLogger());
// Fix:
DataLogger logger = new DataLogger();
sensor.addListener(logger);
// ... when done:
sensor.removeListener(logger);

ThreadLocal Variables Not Cleaned Up

In thread pools, ThreadLocal values survive between tasks because threads are reused. If not cleared, a task's data leaks into subsequent tasks on the same thread.

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-Deployed Apps

In servlet containers, each deployment uses a new classloader. If any class holds a static reference to a class from the old classloader, the entire old classloader (and all its classes) cannot be GCed.

Detecting Leaks with Heap Dumps

Take a heap dump with jmap -dump:format=b,file=heap.hprof <pid>, then open it in Eclipse MAT or VisualVM to find the largest retained objects and their GC roots.

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

Eclipse Memory Analyzer (MAT)

MAT's "Leak Suspects" report automatically identifies objects with large retained heap and shows the path from GC roots. Start with the "Dominator Tree" view to find the biggest culprits.

Using WeakReference to Avoid Leaks

Wrap cached or listener objects in WeakReference. The GC can reclaim them under memory pressure. Always null-check the get() result.

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 GCed

Bounded Caches with LinkedHashMap LRU

Override removeEldestEntry in a LinkedHashMap to cap cache size and evict the least-recently-used entry automatically.

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
    }
};

Profiling Allocations with Java Flight Recorder

JFR (Java Flight Recorder) captures allocation profiles with minimal overhead. Enable with -XX:StartFlightRecording and analyze with 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.jfr

Fixing Leaks: Checklist

Check: static collections, unregistered listeners, ThreadLocals in pools, connection/stream leaks (use try-with-resources), inner class references to outer objects, and caches without eviction.

Quick Check

What JVM flag auto-dumps the heap when OutOfMemoryError is thrown?

Recap

Common Java leak sources: static collections, unregistered listeners, pooled ThreadLocals, and unbounded caches. Detect with heap dumps + MAT. Fix with WeakReferences, bounded structures, and always removing references when done.

Frequently asked questions

Is the “Detecting and Fixing Memory Leaks” lesson free?

Yes — the full text of “Detecting and Fixing Memory Leaks” is free to read here on the web, and the Java Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Java Academy course, upgrade to CoddyKit PRO.

What will I learn in “Detecting and Fixing Memory Leaks”?

Identify common memory leak patterns (static collections, listeners, caches) and fix them. You practise Java Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Java Academy?

No prior experience is required. Java Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Detecting and Fixing Memory Leaks” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Java Academy lesson?

Yes. Every Java Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. JVM Heap Regions and Object Lifecycle
  2. GC Algorithms: Serial, G1, ZGC, Shenandoah
  3. Detecting and Fixing Memory Leaks
  4. GC Tuning Flags and JVisualVM Profiling
← Back to Java Academy