6 Common Java OOM Scenarios and How to Prevent Them

This article explains six typical OutOfMemoryError situations in Java—heap, native thread, stack overflow, direct buffer, GC overhead, and Metaspace—provides code examples that trigger each issue, shows the resulting exception messages, and offers practical tips such as using thread pools, limiting recursion depth, adjusting GC settings, and configuring Metaspace to avoid these memory problems.

Java Backend Technology
Java Backend Technology
Java Backend Technology
6 Common Java OOM Scenarios and How to Prevent Them

Today we discuss six common OOM scenarios that can occur in online services and how to troubleshoot them.

1. Heap Memory OOM

Heap OOM is the most common. The exception is java.lang.OutOfMemoryError: Java heap space, caused when the JVM heap maximum cannot satisfy demand. java.lang.OutOfMemoryError: Java heap space Example code that continuously adds objects to a List in an infinite loop:

public class HeapOOMTest {
    public static void main(String[] args) {
        List<HeapOOMTest> list = Lists.newArrayList();
        while (true) {
            list.add(new HeapOOMTest());
        }
    }
}

The program quickly throws the heap OOM error, which often occurs when exporting massive data sets or loading too many records at once.

2. Native Thread OOM (Stack Memory OOM)

Creating too many threads can exhaust native thread memory, leading to

java.lang.OutOfMemoryError: unable to create new native thread

.

java.lang.OutOfMemoryError: unable to create new native thread

Example that spawns a new Thread in an infinite loop:

public class StackOOMTest {
    public static void main(String[] args) {
        while (true) {
            new Thread().start();
        }
    }
}

The result is a large number of threads and the above error. Recommendation: use thread pools instead of creating raw threads.

Prefer thread pools to avoid this OOM.

3. Stack Overflow

Deep recursive calls can exceed the JVM stack limit, causing java.lang.StackOverflowError. java.lang.StackOverflowError Example of recursive method without depth control:

public class StackFlowTest {
    public static void main(String[] args) {
        doSomething();
    }
    private static void doSomething() {
        doSomething();
    }
}

The program ends with StackOverflowError. Advice: limit recursion depth, add a parameter to stop when a threshold is reached.

When writing recursive code, always control recursion depth to prevent infinite loops.

4. Direct (Off‑Heap) Memory OOM

Direct memory is allocated outside the JVM heap via NIO's DirectByteBuffer. When exhausted, the JVM throws java.lang.OutOfMemoryError: Direct buffer memory.

java.lang.OutOfMemoryError: Direct buffer memory

Example that continuously allocates 20 MB direct buffers:

public class DirectOOMTest {
    private static final int BUFFER = 1024 * 1024 * 20;
    public static void main(String[] args) {
        List<ByteBuffer> list = new ArrayList<>();
        int count = 0;
        try {
            while (true) {
                ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BUFFER);
                list.add(byteBuffer);
                count++;
                Thread.sleep(100);
            }
        } finally {
            System.out.println(count);
        }
    }
}

The program eventually prints the number of allocations and then fails with the Direct buffer memory OOM.

5. GC Overhead OOM

When the garbage collector spends too much time reclaiming memory, the JVM throws java.lang.OutOfMemoryError: GC overhead limit exceeded.

java.lang.OutOfMemoryError: GC overhead limit exceeded

Test configuration: -Xmx10m -Xms10m. Example creates a fixed thread pool and submits endless tasks that sleep, quickly exhausting heap and triggering GC overhead OOM.

public class GCOverheadOOM {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; ; i++) {
            executor.execute(() -> {
                try { Thread.sleep(10000); } catch (InterruptedException e) {}
            });
        }
    }
}

Solution: adjust GC strategy, start GC when old generation reaches ~80 %, and tune -XX:SurvivorRatio and -XX:NewRatio.

6. Metaspace OOM

Since JDK 8, the permanent generation is replaced by Metaspace, which resides in native memory. Exhausting it yields java.lang.OutOfMemoryError: Metaspace. java.lang.OutOfMemoryError: Metaspace Test parameters: -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m. Example repeatedly creates CGLIB enhancers, loading many generated classes until Metaspace is full.

public class MetaspaceOOMTest {
    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOM.class);
            enhancer.setUseCache(false);
            enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> proxy.invokeSuper(obj, args1));
            enhancer.create();
        }
    }
}

The program ends with Metaspace OOM, typically caused by loading too many classes or very large classes.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJVMStackHeapMetaspacegcOutOfMemoryError
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.