JVM memory calculator
Split a container memory limit into heap and everything else, see how much headroom is left, and copy the matching JVM flags and Kubernetes resources.
Why a JVM in a container needs a memory budget
A Java process is more than its heap. When you set a container memory limit of 1 GiB and give the heap 75% of it, the remaining 256 MiB must hold class metadata, compiled code, one stack per thread, direct and mapped buffers, the garbage collector's own data and the native memory of any library you load. Under load that is often more than people expect, and the result is a pod that restarts with exit code 137 and no stack trace.
This calculator makes the budget explicit. Enter the container size and your best estimates for threads, stack size, metaspace, code cache and direct memory. It shows how much is left over, warns when the numbers do not fit, and prints the JVM flags and a Kubernetes snippet to match.
Rules of thumb
- Start with a heap of 60% to 75% of the container and measure the real non-heap usage with Native Memory Tracking (
-XX:NativeMemoryTracking=summary). - Count threads honestly: Tomcat workers, scheduler pools, Kafka clients, connection pool housekeeping and virtual-thread carriers all add stacks.
- Keep at least 10% of the container free for everything the estimate misses.
- Set
-XX:+ExitOnOutOfMemoryErrorso a real heap exhaustion restarts the pod cleanly instead of leaving it half alive.
The estimates are a planning aid, not a measurement. Run the application under realistic load and compare with what the container actually uses before you lower the limit. Nothing you enter leaves your browser.
Frequently asked questions
Why was my container OOM-killed when the heap was below the limit?
The JVM uses memory outside the heap: metaspace, the JIT code cache, thread stacks, direct buffers, GC structures and native libraries. If heap plus all of that exceeds the container limit, the kernel kills the process (exit code 137) and Java never gets to throw OutOfMemoryError.
What does MaxRAMPercentage do?
It sets the maximum heap as a percentage of the memory the JVM sees. Inside a container that is the cgroup limit, because modern JVMs (JDK 10 and later, and 8u191 and later) are container aware. The default is 25%, which is conservative for a dedicated service.
Should I use -Xmx or MaxRAMPercentage?
In containers prefer MaxRAMPercentage, because the heap then scales when you change the memory limit. Use -Xmx when you need an exact size that must not change with the limit.
Which garbage collector will I get?
The JVM picks SerialGC when it sees fewer than 2 CPUs or less than about 1792 MiB of memory, and G1 otherwise. Setting small limits therefore changes the collector as well as the heap.