Java Memory Management
In this page:
Stack vs Heap Memory
Java allocates local variables and method call frames on each thread's own Stack, which is fast and automatically cleaned up when a method returns, while actual object instances live in the shared Heap, which is managed by the garbage collector instead.
Example: Stack vs Heap Memory
public class Main {
static class Point { int x; } // instances live on the Heap
public static void main(String[] args) {
int localVar = 5; // lives on the Stack, cleaned up when main() returns
Point p = new Point(); // the reference is on the Stack, the object itself is on the Heap
System.out.println(localVar + " " + p);
}
}
Login to try C/C++/Java/PHP code in the editor
Memory Leak Identification
Memory leaks in Java happen when code retains references to objects it no longer actually needs -- a growing static list, or an unclosed listener registration -- which prevents the garbage collector from reclaiming those objects even though the program will never use them again.
Example: Memory Leak Identification
import java.util.*;
public class Main {
static List<Object> cache = new ArrayList<>(); // static list -- keeps growing, never cleared
public static void main(String[] args) {
for (int i = 0; i < 5; i++) cache.add(new Object());
System.out.println("Cache size: " + cache.size() + " -- these can never be garbage collected");
}
}
Login to try C/C++/Java/PHP code in the editor
OutOfMemoryError (OOM)
The JVM throws an OutOfMemoryError when heap allocation requests exceed the memory actually available to it, which usually signals either a genuine memory leak or a heap size limit (-Xmx) configured too small for the application's real workload.
Example: OutOfMemoryError (OOM)
public class Main {
public static void main(String[] args) {
try {
int[] huge = new int[Integer.MAX_VALUE]; // exceeds available heap
} catch (OutOfMemoryError e) {
System.out.println("Caught OutOfMemoryError: heap exceeded");
}
}
}
Login to try C/C++/Java/PHP code in the editor
Metaspace Configuration
Class metadata -- the compiled structure of loaded classes themselves, not object instances -- lives in Metaspace, a dynamically-sized memory region that draws from native (off-heap) system memory rather than the regular Java heap.
Example: Metaspace Configuration
public class Main {
public static void main(String[] args) {
// Run with: java -XX:MaxMetaspaceSize=128m Main
System.out.println("Class metadata lives in Metaspace, drawn from native memory, not the heap");
}
}
Login to try C/C++/Java/PHP code in the editor
Finalization and Cleaner API
The Cleaner API offers a safer, more predictable way to release off-heap resources (like native memory or file handles) tied to an object's lifecycle, replacing the old, unreliable Object.finalize() mechanism that the JVM never guaranteed would run promptly, if at all.
Example: Finalization and Cleaner API
import java.lang.ref.Cleaner;
public class Main {
static final Cleaner cleaner = Cleaner.create();
public static void main(String[] args) {
Object resource = new Object();
cleaner.register(resource, () -> System.out.println("Cleaned up off-heap resource"));
resource = null;
System.gc();
}
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 19 topics to unlock
0/19 topics done
Complete these topics first:
- Java Reflection API
- Java Annotations Advanced
- Java Garbage Collection
- Java Memory Management
- Java Performance Optimization
- Java Advanced Interview Questions
- Java CompletableFuture
- Java Atomic Classes
- Java Locks & Semaphores
- Java Concurrent Collections
- Java Cryptography Basics
- Java Hashing (MD5, SHA)
- Java SSL & HTTPS
- Java Logging (Log4j/SLF4J)
- Java Serialization Advanced
- Java Interview Questions Advanced
- Java Connection Pooling
- Java Test Driven Development
- Java Integration Testing