What is OutOfMemoryError
in Java?
The OutOfMemoryError
in Java is a serious runtime error that occurs when the Java Virtual Machine (JVM) runs out of memory and cannot allocate more objects. It belongs to the java.lang.Error
class and is not meant to be caught or handled, but rather prevented through proper memory management.
1. Causes of OutOfMemoryError
🔹 1️⃣ Java Heap Space Exhaustion
- Happens when the JVM heap memory is full, and no additional memory can be allocated.
- Common in applications that create too many objects without proper garbage collection.
✅ Example: Memory Leak Causing OutOfMemoryError
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryHeapExample {
public static void main(String[] args) {
List<int[]> list = new ArrayList<>();
while (true) {
list.add(new int[1_000_000]); // Continuously allocating large memory
}
}
}
🛑 Output:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
✅ Prevention:
- Increase heap size using JVM options:
-Xmx512m
(sets max heap to 512MB). - Use memory profiling tools (e.g., VisualVM, JProfiler) to detect memory leaks.
- Use
WeakReference
for cache-like structures.
🔹 2️⃣ Out of Metaspace (OutOfMemoryError: Metaspace
)
- Happens when too many classes are loaded dynamically, and the Metaspace (class metadata memory area) is exhausted.
- Common in Spring applications, reflection-heavy code, or frequent class loading/unloading.
✅ Example: Excessive Class Loading
import javassist.ClassPool;
public class OutOfMemoryMetaspaceExample {
public static void main(String[] args) throws Exception {
ClassPool classPool = ClassPool.getDefault();
for (int i = 0; ; i++) {
classPool.makeClass("com.example.GeneratedClass" + i).toClass();
}
}
}
🛑 Output:
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
✅ Prevention:
- Increase Metaspace using
-XX:MaxMetaspaceSize=256m
. - Avoid dynamic class generation unless necessary.
🔹 3️⃣ Out of Direct Memory (OutOfMemoryError: Direct buffer memory
)
- Happens when off-heap (direct) memory is exhausted.
- Common in Netty, NIO buffers, and large ByteBuffers.
✅ Example: Exhausting Direct Memory
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryDirectBufferExample {
public static void main(String[] args) {
List<ByteBuffer> buffers = new ArrayList<>();
while (true) {
buffers.add(ByteBuffer.allocateDirect(10 * 1024 * 1024)); // Allocating direct memory
}
}
}
🛑 Output:
Exception in thread "main" java.lang.OutOfMemoryError: Direct buffer memory
✅ Prevention:
- Use
-XX:MaxDirectMemorySize=256m
to limit direct memory. - Avoid unnecessary
ByteBuffer.allocateDirect()
allocations.
🔹 4️⃣ Garbage Collection Overhead (OutOfMemoryError: GC overhead limit exceeded
)
- Happens when too much time is spent on garbage collection but little memory is reclaimed.
- JVM throws this when GC takes > 98% of CPU time but recovers < 2% memory.
✅ Example: Heavy GC Load
import java.util.HashMap;
import java.util.Map;
public class OutOfMemoryGCExample {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
for (int i = 0; ; i++) {
map.put(i, "Memory Leak " + i);
}
}
}
🛑 Output:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
✅ Prevention:
- Increase heap:
-Xmx512m
- Use GC tuning options:
-XX:+UseG1GC
- Enable profiling tools to detect memory leaks.
2. How to Fix OutOfMemoryError
🔹 ✅ Increase JVM Heap Size:
java -Xms256m -Xmx1024m MyApp
🔹 ✅ Detect Memory Leaks Using Profiling Tools:
- Use VisualVM, Eclipse MAT, or JProfiler to analyze heap dumps.
jmap -dump:file=heapdump.hprof <pid>
🔹 ✅ Optimize Data Structures:
- Use
WeakReference
instead of strong references in caches. - Use streams instead of loading large collections into memory.
🔹 ✅ Prevent Unused Object Retention:
List<String> list = new ArrayList<>();
list = null; // Help garbage collector
System.gc(); // Suggest GC to run
3. Can We Catch OutOfMemoryError
?
🚨 Catching OutOfMemoryError
is not recommended, but you can if you want to log or perform cleanup.
public class CatchOutOfMemoryExample {
public static void main(String[] args) {
try {
List<int[]> list = new ArrayList<>();
while (true) {
list.add(new int[1_000_000]);
}
} catch (OutOfMemoryError e) {
System.err.println("Out of Memory! Freeing resources...");
}
}
}
✅ Best Practice: Instead of catching, prevent it with good memory management.
4. Summary Table
OutOfMemoryError Type | Cause | Fix |
---|---|---|
Java Heap Space | Too many objects in heap | Increase -Xmx , fix memory leaks |
Metaspace | Too many loaded classes | Increase MaxMetaspaceSize , reduce dynamic class loading |
Direct Buffer Memory | Excessive NIO buffers | Limit MaxDirectMemorySize , reuse buffers |
GC Overhead | Excessive GC time | Use better GC (-XX:+UseG1GC ), optimize collections |
Final Thoughts
✔ OutOfMemoryError
is a serious JVM error caused by memory leaks or insufficient memory.
✔ Instead of handling it, focus on preventing it through memory optimization.
✔ Profiling tools like VisualVM and Eclipse MAT help detect memory leaks.
✔ Proper GC tuning and heap size adjustments can mitigate the issue.