DEV Community

Neeraj Gahlawat
Neeraj Gahlawat

Posted on

Detecting & Fixing Memory Leaks in Java (Spring Boot) β€” A Practical Guide

🧠 Introduction

Memory leaks are one of the most dangerous performance issues in Java applications. They silently consume heap memory, degrade performance, and eventually crash production systems.

Even though Java uses Garbage Collection, memory leaks still happen when objects remain referenced and cannot be cleaned up.

In this guide, you will learn:

βœ” What memory leaks are
βœ” How to detect them
βœ” Tools professionals use
βœ” How to fix them
βœ” A working Spring Boot demo example

🚨 What is a Memory Leak?

A memory leak occurs when:

Objects are no longer needed but are still referenced, preventing Garbage Collection.

Over time, heap usage grows until the application throws:

java.lang.OutOfMemoryError: Java heap space

πŸ”₯ Common Causes of Memory Leaks
1️⃣ Static Collections Holding Objects
public class CacheStore {
public static List cache = new ArrayList<>();
}

❌ Objects never released
βœ” Heap memory keeps growing

2️⃣ Unclosed Resources
Connection conn = dataSource.getConnection();

❌ Connection not closed β†’ resource leak

βœ” Use try-with-resources:

try(Connection conn = dataSource.getConnection()) {
// use connection
}

3️⃣ ThreadLocal Misuse

Improper ThreadLocal cleanup can leak memory in thread pools.

4️⃣ Listener & Callback References

Listeners registered but never removed remain in memory.

πŸ”¬ How to Detect Memory Leeks
βœ… Step 1: Monitor Heap Usage

Use:

βœ” JVisualVM
βœ” JConsole
βœ” Micrometer + Prometheus
βœ” Grafana dashboards

If heap memory keeps growing β†’ leak suspected.

βœ… Step 2: Generate Heap Dump

Run:

jmap -dump:live,format=b,file=heap.hprof

βœ… Step 3: Analyze Heap Dump

Use:

πŸ›  Eclipse Memory Analyzer Tool (MAT)

Open heap dump β†’ check:

βœ” Dominator Tree
βœ” Leak Suspects Report
βœ” Objects retaining memory

πŸ§ͺ Spring Boot Memory Leak Demo
Leak Code Example

@RestController
public class LeakController {

    private static final List<byte[]> memoryLeak = new ArrayList<>();

    @GetMapping("/leak")
    public String leak() {
        memoryLeak.add(new byte[1024 * 1024]); // 1MB
        return "Added";
    }
}

Enter fullscreen mode Exit fullscreen mode

Every call adds 1MB β†’ memory grows continuously.

πŸ“Š Memory Leak Behavior
BEFORE FIX

βœ” Heap usage continuously increases
βœ” GC unable to reclaim memory
βœ” Application slows down

AFTER FIX

βœ” Memory stabilizes
βœ” GC reclaims unused objects
βœ” Performance improves

πŸ›  Fixing the Leak
❌ Problem

Unbounded static list storing objects.

βœ… Solution Options

βœ” Limit cache size
βœ” Remove unused objects
βœ” Use WeakReference
βœ” Use caching libraries (Caffeine, EhCache)

Example fix:

private static final List<byte[]> memoryLeak = new ArrayList<>();

@GetMapping("/fix")
public String fix() {
    if(memoryLeak.size() > 10) {
        memoryLeak.clear();
    }
    memoryLeak.add(new byte[1024 * 1024]);
    return "Managed";
}

Enter fullscreen mode Exit fullscreen mode

πŸ“ˆ Production Monitoring Best Practices

βœ” Enable GC logging
βœ” Track heap usage metrics
βœ” Set memory alerts
βœ” Run periodic heap analysis
βœ” Load test before release

🧰 Tools Professionals Use

βœ” VisualVM
βœ” Eclipse Memory Analyzer Tool
βœ” JProfiler
βœ” YourKit

🎯 Key Takeaways

βœ… Garbage Collection does NOT prevent memory leaks
βœ… Static references are common leak sources
βœ… Heap dump analysis is essential
βœ… Monitoring prevents production failures

πŸ”— GitHub Demo Repository

πŸ‘‰ Add your GitHub link here

Example:https://github.com/yourusername/spring-boot-memory-leak-demo

πŸš€ Conclusion

Memory leaks are silent killers of application performance. By monitoring memory usage, analyzing heap dumps, and following best coding practices, you can prevent crashes and ensure system stability.

Top comments (0)