Memory leaks in Java occur when objects that are no longer needed remain reachable through active references, preventing the Garbage Collector from reclaiming their memory. To debug such issues, I would monitor memory usage, capture heap dumps, analyze object retention paths, and identify the code that is holding unnecessary references.
Key Points: • Monitor heap utilization using tools such as VisualVM, Java Flight Recorder (JFR), JConsole, or JProfiler to detect abnormal memory growth. • Capture and analyze heap dumps using Eclipse Memory Analyzer (MAT) to identify large objects, memory hotspots, and retention chains. • Look for common leak sources such as static collections, unclosed resources, listener registrations, ThreadLocal misuse, and improperly managed caches.
Example: Suppose a web application stores user sessions in a static Map but never removes expired sessions. Even after users log out, the session objects remain referenced by the Map, causing memory usage to grow continuously until performance degrades or an OutOfMemoryError occurs.
Code Example:
import java.util.HashMap;
import java.util.Map;
public class SessionCache {
private static final Map<String, Object> cache =
new HashMap<>();
public static void addSession(String id,
Object session) {
cache.put(id, session);
}
// Expired sessions should be removed
public static void removeSession(
String id) {
cache.remove(id);
}
}Interview Tip: A concise interview answer is: To debug a memory leak, I monitor heap usage, collect heap dumps, and analyze them using tools like Eclipse MAT or VisualVM. I then identify objects that are being retained unexpectedly, trace their reference paths, fix the code holding those references, and validate the solution through memory monitoring and load testing.