Java.What do you know about OutOfMemoryError?

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 TypeCauseFix
Java Heap SpaceToo many objects in heapIncrease -Xmx, fix memory leaks
MetaspaceToo many loaded classesIncrease MaxMetaspaceSize, reduce dynamic class loading
Direct Buffer MemoryExcessive NIO buffersLimit MaxDirectMemorySize, reuse buffers
GC OverheadExcessive GC timeUse 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.

This entry was posted in Без рубрики. Bookmark the permalink.