What Are Xmx and Xms in Java?
-Xmx sets the maximum size of the Java heap, and -Xms sets its initial size. Both are flags passed to the java command, for example java -Xms2g -Xmx2g -jar app.jar. The heap is the memory region where the JVM stores every object your program creates and where the garbage collector reclaims space. If live objects need more than -Xmx, the JVM throws java.lang.OutOfMemoryError: Java heap space.
The names are not acronyms. The -X prefix marks a HotSpot option that is not part of the Java standard. A common reading is "ms" for memory start and "mx" for memory maximum. The flags are the same on Linux, Windows and macOS, and on every HotSpot-based JDK from Oracle, OpenJDK, Amazon Corretto and Eclipse Temurin.
Syntax and units
The size follows the flag directly, with no space and no equals sign. -Xmx 4g and -Xmx=4g are both errors.
| Flag | What it sets | Example | Rule |
|---|---|---|---|
-Xms<size> | Initial heap size | -Xms512m | A multiple of 1024, greater than 1 MB |
-Xmx<size> | Maximum heap size | -Xmx4g | A multiple of 1024, greater than 2 MB, at least -Xms |
-Xmn<size> | Size of the young generation, where new objects are created | -Xmn1g | Leave unset with the G1 collector, which sizes it adaptively |
-Xss<size> | Stack size per thread | -Xss512k | Default is 1 MB on 64-bit Linux and Windows |
-XX:MaxRAMPercentage=<n> | Maximum heap as a percentage of available memory | -XX:MaxRAMPercentage=75.0 | Container-friendly alternative to -Xmx |
-XX:InitialRAMPercentage=<n> | Initial heap as a percentage | -XX:InitialRAMPercentage=75.0 | Alternative to -Xms |
The unit suffix is k or K for kilobytes, m or M for megabytes and g or G for gigabytes. A number with no suffix is bytes. The units are binary, so 1g equals 1024m. Searches for "xmnx" are usually a misspelling of -Xmn or -Xmx; there is no flag by that name.
Defaults when you set nothing
On a machine or container with 2 GB or more of memory, HotSpot picks the maximum heap as one quarter of physical memory and the initial heap as one sixty-fourth. An 8 GB container with no flags therefore gets a 2 GB maximum heap and a 128 MB initial heap. From JDK 10, and from update 191 of JDK 8, physical memory means the container's cgroup limit rather than the host's RAM.
You can print the values the JVM has chosen without running your application.
java -XX:+PrintFlagsFinal -version | grep -Ei "MaxHeapSize|InitialHeapSize|MaxRAMPercentage"
For a running process, jcmd <pid> VM.flags prints the same values, and Runtime.getRuntime().maxMemory() returns the maximum heap from inside the program.
Xmx versus Xms: what each one changes
| -Xms (initial) | -Xmx (maximum) | |
|---|---|---|
| Set too low | The JVM grows the heap in steps after startup, and each step involves a garbage collection | OutOfMemoryError once live data exceeds the limit |
| Set too high | Memory is committed that the application never uses | Heap plus non-heap memory exceed the container limit, and the kernel kills the process with exit code 137 |
| Typical value for a service | Equal to -Xmx | 50 to 75 percent of the container's memory limit |
The exit code 137 case is worse than the Java exception. There is no stack trace, no heap dump, and the log ends mid-line. It happens because -Xmx limits only the heap. Thread stacks, class metadata (metaspace), the JIT code cache, garbage collector data and direct byte buffers for network I/O all live outside it.
Setting -Xms equal to -Xmx is the usual choice for a long-running service. The heap never resizes, so there are no resize-triggered collections and the memory use is predictable from the first second. For a short command-line tool, leaving -Xms at its default lets the JVM start with a small heap and finish before it ever grows.
Worked example: sizing a service
Suppose a Spring Boot API runs in a container with a 4 GB memory limit and a pool of 200 request threads. The heap is sized by subtracting the non-heap budget from the limit.
- Thread stacks. 200 threads x 1 MB = 200 MB. Setting
-Xss512khalves that if the stacks are shallow. - Metaspace and code cache. A typical Spring application uses 100 to 200 MB of class metadata and up to 240 MB of compiled code.
- Direct buffers and collector data. Allow about 200 MB for network buffers and the collector's own structures.
- Total non-heap. Roughly 700 MB to 1 GB. Round up to 1 GB.
- Heap. 4 GB minus 1 GB leaves 3 GB. Set -Xms and -Xmx both to 3g.
java -Xms3g -Xmx3g -Xss512k -XX:+UseG1GC -Xlog:gc:file=/var/log/api/gc.log -jar api.jar
The percentage form gives the same result and follows the limit if the container is resized.
java -XX:InitialRAMPercentage=75.0 -XX:MaxRAMPercentage=75.0 -jar api.jar
Verify under a load test by reading the garbage collection log. After a full collection, the live data should occupy about a third to a half of the heap. If it occupies more than 70 percent, the heap is too small and collections will run constantly. If it occupies under 20 percent, memory is being wasted and a smaller container would do.
Where to put the flags
On the command line, the flags go before -jar. In a container image, the environment variable JAVA_TOOL_OPTIONS is read by every JVM at startup, so JAVA_TOOL_OPTIONS="-Xms3g -Xmx3g" works without editing the start command. Tomcat reads CATALINA_OPTS, and most application servers have an equivalent. Maven and Gradle builds read MAVEN_OPTS and org.gradle.jvmargs respectively.
Key Takeaways
- -Xms is the initial heap and -Xmx is the maximum heap. Write them as
-Xms2g -Xmx2g, with no space or equals sign. - Units are k, m and g, and the values are binary, so 1g is 1024m.
- With no flags, the maximum heap is one quarter of the container's memory and the initial heap is one sixty-fourth.
- For a service, set both flags to the same value, at 50 to 75 percent of the container limit, and leave the rest for stacks, metaspace and buffers.
Grokking System Design Fundamentals covers the memory and capacity estimates that this sizing exercise is part of.
Grokking the System Design Interview shows where JVM services sit in a full system design answer.
Grokking Multithreading and Concurrency for Coding Interviews explains the thread pools whose stacks appear in the non-heap budget above.

GET YOUR FREE
Coding Questions Catalog

$123

$197

$72