/flags/java/java-xmx-max-heap-size
java -Xmx: set the maximum heap size (and fix OutOfMemoryError: Java heap space)
- tool
- Java
- command
- java
- flag
- -Xmx<size>
- default
- 1/4 of physical memory (JVM ergonomics) when not set
java -Xmx512m -jar app.jar caps the Java heap at 512 MiB. When the program needs more heap than that, the JVM throws java.lang.OutOfMemoryError: Java heap space. Without -Xmx the JVM chooses the limit itself, by default one quarter of the machine's physical memory. The value takes a unit suffix: k/K, m/M or g/G; a number without a suffix means bytes. The equivalent long option is -XX:MaxHeapSize=<size>.
Setting it and hitting it
cat > Mem.java <<'EOF'
public class Mem {
public static void main(String[] args) {
long max = Runtime.getRuntime().maxMemory() / (1024 * 1024);
System.out.println("max heap (MiB): " + (max > 1000 ? "more than 1000" : String.valueOf(max)));
if (args.length > 0) {
java.util.List<byte[]> keep = new java.util.ArrayList<>();
while (true) keep.add(new byte[1024 * 1024]);
}
}
}
EOF
echo "== default"
java Mem.java
echo "== -Xmx64m"
java -Xmx64m Mem.java
java -Xmx64m -XX:+PrintFlagsFinal -version 2>/dev/null | grep -E ' MaxHeapSize ' | awk '{print $2, $3, $4}'
echo "== -Xmx64m, filling the heap"
java -Xmx64m Mem.java fill; echo "exit: $?"
echo "== -Xmx64 (no unit = bytes)"
java -Xmx64 Mem.java; echo "exit: $?"Output
== default max heap (MiB): more than 1000 == -Xmx64m max heap (MiB): 64 MaxHeapSize = 67108864 == -Xmx64m, filling the heap max heap (MiB): 64 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at Mem.main(Mem.java:7) exit: 1 == -Xmx64 (no unit = bytes) Error occurred during initialization of VM Too small maximum heap exit: 1
With -Xmx64m the JVM reports a 64 MiB maximum (MaxHeapSize = 67108864 bytes), and the program that keeps allocating dies with OutOfMemoryError: Java heap space and exit code 1. Forgetting the unit asks for 64 bytes, which the JVM refuses at start-up with Too small maximum heap.
Related memory options
| Option | What it sets | Notes |
|---|---|---|
| -Xmx<size> | Maximum heap size | Same as -XX:MaxHeapSize |
| -Xms<size> | Initial heap size | Set equal to -Xmx on servers to avoid resizing |
| -XX:MaxRAMPercentage=<pct> | Maximum heap as a percentage of available memory | Container-friendly; ignored if -Xmx is set |
| -XX:InitialRAMPercentage=<pct> | Initial heap as a percentage | Pairs with MaxRAMPercentage |
| -Xss<size> | Thread stack size | For StackOverflowError, not heap problems |
| -XX:MaxMetaspaceSize=<size> | Limit for class metadata | OutOfMemoryError: Metaspace |
| -XX:+HeapDumpOnOutOfMemoryError | Write an .hprof heap dump when the heap runs out | Analyse it with a heap analyser to find the leak |
Where to put it
java -Xmx2g -jar app.jar # command line (before -jar or the class name)
JAVA_TOOL_OPTIONS="-Xmx2g" java -jar app.jar # environment, picked up by every JVM
java -XX:MaxRAMPercentage=75 -jar app.jar # containers: 75% of the memory limit
./gradlew build -Dorg.gradle.jvmargs=-Xmx2g # Gradle daemon (or org.gradle.jvmargs in gradle.properties)
MAVEN_OPTS="-Xmx2g" mvn package # MavenJVM options must come before the main class or -jar app.jar. Anything after it is passed to your program as an argument; a typo there turns into an unexpected argument, while a typo before it can be read as the class name and end in Could not find or load main class.
Diagnosing heap problems
OutOfMemoryError: Java heap spacewith a small-Xmxand a legitimate workload: raise-Xmx.- The same error with any
-Xmx: probably a leak (a growing cache or collection); a bigger heap only delays it. Run with-XX:+HeapDumpOnOutOfMemoryErrorand inspect the dump. GC overhead limit exceeded: the JVM spends almost all its time in garbage collection with very little reclaimed, another sign that the heap is nearly full.- The process is killed by the OS or container (exit 137 on Linux) without an
OutOfMemoryError: total memory, not the heap, exceeded the limit; lower-Xmxor raise the container limit.
FAQ
What is the default maximum heap size in Java?
When -Xmx is not set, the JVM ergonomics pick one quarter of the physical memory as the maximum heap, as described in the Java garbage collection tuning guide. In containers, recent JVMs use the container memory limit instead of the host memory.
Should -Xms be equal to -Xmx?
For servers with a known memory budget, setting both to the same value avoids heap resizing pauses and makes the memory use predictable. For desktop tools and short-lived programs, leave -Xms unset so the JVM starts small.
Does -Xmx limit the total memory of the java process?
No. It limits only the Java heap. Metaspace, thread stacks, the code cache, direct buffers and the JVM itself use memory on top of it, so a container needs headroom above the -Xmx value.