How a Misconfigured JVM Parameter Triggered a Production OOM Disaster

A production outage at Company A was traced to an incorrect JVM -Xmn setting that matched -Xmx, causing the young generation to consume the entire heap and repeatedly trigger Full GC and OutOfMemoryError, a lesson on careful JVM tuning and script management.

Java Interview Crash Guide
Java Interview Crash Guide
Java Interview Crash Guide
How a Misconfigured JVM Parameter Triggered a Production OOM Disaster

Incident Background

On March 10, 2023, Company A reported that an open API became inaccessible. Network checks were normal, and a service restart temporarily restored functionality, but the issue recurred within minutes, leading to an emergency rollback to a stable version.

Incident Analysis

Logs revealed OutOfMemoryError: Java heap space, prompting the addition of

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/app/logs/app.dump

to the startup script. The dump file contained multiple OOM errors at different locations, but memory analysis with MAT showed only about 100 MB of live objects, offering no clear culprit.

Possible causes considered were excessive data loading, memory leaks, and insufficient system memory. System memory (16 GB) and the Java process (≈7.8 GB) appeared adequate.

Comparison of old and new startup scripts revealed a critical change:

-Xms8g -Xmx8g -Xmn3g
-Xmx : maximum heap size -Xms : initial heap size -Xmn : young generation size
-Xms8g -Xmx8g -Xmn8g

The new script set the young generation size equal to the maximum heap size.

Root Cause

In JDK 8, Heap Space Size = Young Space Size + Old Space Size. Setting -Xmn equal to -Xmx makes the young generation occupy the entire heap, leaving no room for the old generation when objects are promoted, leading to Full GC and OOM errors.

Objects can move to the old generation after surviving many GCs, allocating large objects, or when Eden plus survivor spaces exceed the old generation capacity.

Therefore, -Xmn must be smaller than -Xmx to avoid OOM.

Verification Example

A simple SpringBoot application was built to reproduce the issue. It was started with:

java -Xms512m -Xmx512m -Xmn512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -jar oom-1.0.0-RELEASE.jar

Using ab with 2 concurrent requests caused repeated OOM errors, visible in the console and GC logs, showing the old generation exhausted.

Adjusting the startup parameters to -Xmn64m while keeping -Xmx at 512 m resolved the issue.

Postmortem

Application startup scripts should be treated as code, included in testing and release checklists, and not changed arbitrarily.

Default JVM settings are often safe; over‑tuning can introduce severe problems.

JVM memory model diagram
JVM memory model diagram
JavaJVMOutOfMemoryErrorheapdumpXmn
Java Interview Crash Guide
Written by

Java Interview Crash Guide

Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.

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.