Common Java OOM Types and How to Answer Interview Questions
The article lists the most frequent Java OutOfMemoryError variants, explains their root causes and typical scenarios, provides concrete code examples that trigger each error, and offers practical troubleshooting steps and JVM tuning recommendations for interview preparation.
java.lang.OutOfMemoryError: Java heap space
Trigger: Heap memory is exhausted and cannot allocate new objects.
Typical scenarios:
Memory leak – objects are unintentionally retained (e.g., static collections, unclosed resources) and cannot be GC‑ed.
Insufficient heap size – the -Xmx parameter is set too low or the program processes more data than expected.
Large object allocation – a single massive allocation such as a huge array.
Example:
// Continuously add objects to a collection until the heap overflows
List<Object> list = new ArrayList<>();
while (true) {
list.add(new Object());
}Solutions:
Inspect memory leaks with jmap + MAT to analyze heap dumps.
Increase heap size using -Xmx and -Xms.
Optimize code logic to reduce object lifetimes.
java.lang.OutOfMemoryError: Metaspace (Java 8+) or PermGen space (Java 7-)
Trigger: Metaspace/PermGen runs out of memory, which stores class metadata.
Typical scenarios:
Generating many classes dynamically (e.g., CGLib, reflection, dynamic proxies).
Classloader leaks – old classes are not unloaded after frequent web‑app redeployments.
Example:
// Dynamically generate a large number of proxy classes with CGLib
Enhancer enhancer = new Enhancer();
while (true) {
enhancer.setSuperclass(OOM.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> proxy.invokeSuper(obj, args));
enhancer.create();
}Solutions:
Increase metaspace size with -XX:MaxMetaspaceSize.
Check for classloader leaks or excessive dynamic class generation.
java.lang.OutOfMemoryError: Direct buffer memory
Trigger: Direct (off‑heap) memory allocated via ByteBuffer.allocateDirect() is exhausted.
Typical scenarios:
Frequent direct‑memory allocations without timely release (relying on System.gc() or Cleaner).
JVM parameter -XX:MaxDirectMemorySize set too low.
Example:
// Continuously allocate 1 MB direct buffers
List<ByteBuffer> buffers = new ArrayList<>();
while (true) {
buffers.add(ByteBuffer.allocateDirect(1024 * 1024)); // 1 MB
}Solutions:
Audit code that uses direct memory and ensure buffers are released.
Increase -XX:MaxDirectMemorySize as needed.
java.lang.OutOfMemoryError: Unable to create new native thread
Trigger: Operating‑system limit on thread count is reached.
Typical scenarios:
Thread count exceeds system limits (e.g., Linux ulimit -u).
Per‑thread stack size ( -Xss) is too large, causing total memory consumption to exceed limits.
Example:
// Create threads indefinitely
while (true) {
new Thread(() -> {
try { Thread.sleep(1000000); } catch (InterruptedException e) {}
}).start();
}Solutions:
Reduce thread count by using a thread pool.
Decrease stack size with -Xss.
Raise the OS thread limit.
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
Trigger: Attempt to allocate an array larger than the JVM limit (near Integer.MAX_VALUE).
Typical scenario: Miscalculating array length, e.g., new int[Integer.MAX_VALUE].
Solution: Review array size calculations and use appropriate data structures.
java.lang.OutOfMemoryError: GC Overhead limit exceeded
Trigger: GC runs excessively (e.g., 98 % of time spent in GC) but recovers very little memory.
Typical scenario: Heap is almost full and many objects cannot be reclaimed (often due to memory leaks).
Solution: Investigate memory leaks, adjust heap size, or switch to a different garbage collector.
java.lang.OutOfMemoryError: CodeCache (JIT code cache overflow)
Trigger: JIT‑compiled native code fills the code cache.
Typical scenario: High‑frequency dynamic compilation of many methods (hot code paths).
Solutions:
Increase code cache size with -XX:ReservedCodeCacheSize.
Disable tiered compilation using -XX:-TieredCompilation.
Summary
The root cause of any OOM error is insufficient JVM memory in a specific region (heap, metaspace, direct memory, native thread resources, etc.) or overall resource exhaustion. To diagnose, first identify the error type from the stack trace, then use tools such as jstat, jmap, VisualVM, or MAT to analyze memory usage, and finally adjust JVM parameters or refactor code accordingly.
Typical troubleshooting steps:
Determine the OOM type by examining the exception message.
Analyze memory with profiling tools ( jstat, jmap, VisualVM, MAT).
Modify JVM flags ( -Xmx, -XX:MaxMetaspaceSize, -XX:MaxDirectMemorySize, -Xss, etc.) or improve code to reduce allocations.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer XiaoFu
xiaofucode.com – a programmer learning guide driven by the pursuit of profit
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
