Memory Leaks in Java
A memory leak in Java happens when objects are no longer needed but still cannot be garbage collected because some part of the program holds a reference to them.
While Java has automatic garbage collection, memory leaks can still occur due to improper handling of references.
Memory leaks reduce available heap space, cause performance issues, and may lead to OutOfMemoryError.
What Causes Memory Leaks in Java?
The most common sources of leaks are:

1. Unclosed Resources (Common Cause)
Resources like:
- File streams
- Database connections
- Sockets
- Network streams
If not closed properly, they occupy memory permanently.
Example:
FileInputStream fis = new FileInputStream("data.txt");
// Not closed → memory leak
Always use try-with-resources.
2. Static Variables Holding Objects
Static variables live till the program ends.
If they store large objects → memory leak.
static List<String> cache = new ArrayList<>(); // Grows forever
3. Long-Lived Collections
Collections like:
- ArrayList
- HashMap
- HashSet
- LinkedList
If items are added but never removed → memory leak.
Example:
Map<String, Object> map = new HashMap<>();
map.put("key", new Object()); // stays in memory forever if not removed
4. Inner Classes Holding Outer Class Reference
Anonymous or inner classes implicitly hold a reference to their outer class.
If used inside static contexts → leak risk.
5. Listeners, Observers, Callbacks
Forgotten registrations cause memory retention.
button.addListener(listener); // Never removed
6. ThreadLocal Misuse
ThreadLocal values remain until:
- Thread dies OR
- You manually remove them
If not removed, they cause leaks in thread pools.
7. StringBuilder / StringBuffer Misuse
Large temporary buffers kept in memory cause leaks.
How to Detect Memory Leaks

1. Heap Dump Analysis
Tools:
- Eclipse MAT
- VisualVM
- jProfiler
- YourKit
Check for:
- Retained size
- Unused objects
- Leaking collections
2. Profilers (Real-Time Monitoring)
Track:
- Heap usage
- Thread usage
- GC frequency
3. GC Logs
Enable GC logs to identify unusual heap retention:
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
Memory Leak Example
public class LeakExample {
private static List<int[]> list = new ArrayList<>();
public static void main(String[] args) {
while (true) {
list.add(new int[100000]); // continuously growing
}
}
}
Eventually → OutOfMemoryError.
How to Prevent Memory Leaks (Best Practices)
1. Use Try-with-Resources
Automatically closes resources.
try (FileInputStream fis = new FileInputStream("a.txt")) {
// code
}
2. Remove Unused Objects from Collections
list.remove(obj);
map.clear();
3. Avoid Unnecessary Static References
Don’t store huge data in static variables.
4. Dereference When Not Needed
object = null;
5. Use Weak / Soft References for Caches
(Learn this in next topic)
6. Clean Up Listeners / Observers
button.removeListener(listener);
7. Use ThreadLocal Carefully
Always remove:
threadLocal.remove();
8. Monitor Heap Regularly in Production
Set alerts for:
- Old Gen growth
- GC pauses
- High retention
Real-World Example of a Memory Leak
Leaking due to Cached Data
class Cache {
private static Map<String, byte[]> images = new HashMap<>();
public static void loadImage(String key) {
images.put(key, new byte[5 * 1024 * 1024]); // 5 MB each
}
}
Large cache + no eviction → heavy memory leak.
Use:
- LRU Cache
- SoftReference
- WeakHashMap
Points to Remember
- Java applications can experience memory leaks
- Most leaks occur due to unreleased references
- Tools like MAT, VisualVM, JProfiler help detect them
- Use best practices to keep heap clean
- Understanding GC + memory areas is essential for avoiding leaks
