Question
What do the -Xms and -Xmx parameters mean when starting a JVM, and what are their default values?
For example, in a Java application started from the command line, how do these options affect memory usage, and how can you tell what values are used if you do not set them explicitly?
Short Answer
By the end of this page, you will understand that -Xms sets the JVM's initial heap size and -Xmx sets the maximum heap size. You will also learn why these values matter, how JVM defaults are chosen, why the defaults are not fixed across all machines and Java versions, and how developers typically configure them in real Java applications.
Concept
The main concept behind -Xms and -Xmx is JVM heap memory configuration.
In Java, objects are usually created in a region of memory called the heap. The JVM manages this memory automatically using garbage collection. When you start a Java program, the JVM decides how much heap memory to reserve at first and how much it is allowed to grow.
-Xms= initial heap size-Xmx= maximum heap size
For example:
java -Xms256m -Xmx1024m MyApp
This means:
- start the JVM with 256 MB of heap
- allow the heap to grow up to 1024 MB (1 GB)
Why this matters:
- If the heap is too small, your program may run out of memory with
OutOfMemoryError. - If the heap is too large, your app may waste memory or put pressure on the machine.
- Heap sizing affects performance, startup behavior, and garbage collection.
About default values
A common beginner mistake is expecting one universal default. There is no single fixed default value for -Xms and -Xmx that applies to every JVM.
Defaults depend on things like:
- Java version
- JVM implementation
- operating system
- machine RAM
- whether the JVM detects container limits
- server-class vs client-style behavior in older JVMs
So the correct idea is:
- the JVM chooses defaults automatically if you do not set them
- those defaults are ergonomic, meaning they are calculated based on the environment
- to know the actual values, you should inspect the running JVM or print JVM flags
In practice, many JVMs choose:
- a relatively small initial heap by default
- a maximum heap that is some fraction of available memory
But you should not rely on hardcoded numbers unless you have checked the exact JVM version and environment.
Mental Model
Think of the heap like a warehouse for Java objects.
-Xmsis the size of the warehouse when the business opens.-Xmxis the maximum size the warehouse is allowed to expand to.
If you start with a tiny warehouse, the business may need to expand it later. That can be fine, but resizing may have some overhead.
If you allow the warehouse to grow too large, it may take up space that other programs also need.
So:
-Xmscontrols the starting space-Xmxcontrols the upper limit
The JVM acts like a warehouse manager that tries to choose sensible defaults when you do not provide them yourself.
Syntax and Examples
Basic syntax
java -Xms<size> -Xmx<size> MyApp
Common size suffixes:
k= kilobytesm= megabytesg= gigabytes
Examples:
java -Xms128m -Xmx512m MyApp
java -Xms1g -Xmx4g MyApp
What each one means
java -Xms256m -Xmx1g MyApp
This tells the JVM:
- begin with 256 MB of heap
- never grow beyond 1 GB of heap
A simple Java example
public class HeapInfo {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
System.out.println("Max heap: " + maxMemory / (1024 * 1024) + " MB");
System.out.println("Current heap size: " + totalMemory / (1024 * 1024) + " MB");
System.out.println("Free memory in current heap: " + freeMemory / (1024 * 1024) + " MB");
}
}
Example run:
java -Xms128m -Xmx512m HeapInfo
Possible output:
Max heap: 512 MB
Current heap size: 128 MB
Free memory in current heap: 126 MB
Explanation:
maxMemory()is close to the value from-XmxtotalMemory()is the heap currently allocated, often starting near-XmsfreeMemory()is the unused space within the currently allocated heap
Checking defaults from the JVM
A common way to inspect JVM-chosen values is:
java -XX:+PrintFlagsFinal -version | grep -E "InitialHeapSize|MaxHeapSize"
On Windows PowerShell, you might use:
java -XX:+PrintFlagsFinal -version | Select-String "InitialHeapSize|MaxHeapSize"
This prints the actual values selected by your JVM.
Step by Step Execution
Consider this program:
public class HeapInfo {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
System.out.println("Max heap: " + runtime.maxMemory());
System.out.println("Current heap: " + runtime.totalMemory());
System.out.println("Free in current heap: " + runtime.freeMemory());
}
}
Run it like this:
java -Xms64m -Xmx256m HeapInfo
Step by step
- The JVM starts.
- It reads
-Xms64m, so it begins with about 64 MB of heap. - It reads
-Xmx256m, so it may expand the heap up to about 256 MB if needed. - The
mainmethod runs. Runtime.getRuntime()returns an object that gives information about the JVM runtime.runtime.maxMemory()returns the maximum heap limit, which is typically near256 MB.runtime.totalMemory()returns the amount of heap currently allocated, typically near64 MBat startup.runtime.freeMemory()returns how much of that currently allocated heap is still unused.
Important detail
totalMemory() is not the same as maxMemory().
totalMemory()= heap currently allocated nowmaxMemory()= upper limit the JVM is allowed to use
So the heap can start smaller and grow later until it reaches -Xmx.
Real World Use Cases
1. Running a web application
A Spring Boot service may need a controlled heap size in production:
java -Xms512m -Xmx512m -jar app.jar
This gives the service a predictable heap size and avoids resizing during startup.
2. Running batch jobs
A data-processing job that loads many records into memory may need a larger max heap:
java -Xms1g -Xmx4g -jar batch-job.jar
3. Limiting memory in shared servers
If multiple applications run on the same machine, each process should have a memory limit so one app does not consume all RAM.
4. Containers and cloud deployments
In Docker or Kubernetes, heap settings are often tuned so the JVM stays within the container memory limit.
5. Debugging memory issues
If an app crashes with java.lang.OutOfMemoryError: Java heap space, checking and tuning -Xmx is one of the first troubleshooting steps.
Real Codebase Usage
In real projects, developers rarely think of -Xms and -Xmx as just command-line flags. They are usually part of deployment and performance tuning.
Common patterns
Fixed-size heap for predictable services
Many backend services use the same value for both:
-Xms512m -Xmx512m
Why:
- more predictable memory behavior
- avoids heap expansion during runtime
- easier operational monitoring
Larger max heap than initial heap
Some apps start small and grow as needed:
-Xms256m -Xmx2g
Why:
- reduces initial memory usage
- useful for apps with variable workload
Configuration via environment variables
Real deployments often store JVM options outside code:
JAVA_OPTS="-Xms512m -Xmx1g"
java $JAVA_OPTS -jar app.jar
This keeps memory settings configurable per environment.
Memory tuning alongside monitoring
Teams usually combine heap settings with:
- GC logs
- container memory limits
- application metrics
- heap dump settings for troubleshooting
Validation and operations mindset
Developers do not guess heap size blindly. They usually:
- measure memory usage
- set safe limits
- load test the app
- monitor for GC pressure and
OutOfMemoryError
So in real codebases, heap settings are part of runtime configuration, not application logic.
Common Mistakes
1. Thinking -Xms is the current memory usage
-Xms is the initial heap size, not how much memory the app is using right now.
2. Thinking -Xmx is total system memory
-Xmx only limits the Java heap. A Java process also uses memory for:
- metaspace
- thread stacks
- direct buffers
- JVM internals
- native libraries
So a process can use more memory than the -Xmx value.
3. Assuming default values are always the same
Broken assumption:
The default -Xmx is always 256m
This is not reliable. Defaults vary by JVM and environment.
4. Setting -Xmx larger than available memory
Example:
java -Xmx64g MyApp
If the machine or container does not have enough memory, the app may fail or the OS may start killing processes.
5. Confusing heap growth with object lifetime
Even if the heap can grow to -Xmx, unused objects can still be garbage-collected. Heap size and object lifetime are related but not the same thing.
6. Using invalid sizes
Broken example:
java -Xms512 -Xmx1024 MyApp
This is ambiguous and may not behave as expected depending on the JVM. Prefer explicit units:
java -Xms512m -Xmx1024m MyApp
7. Ignoring container memory limits
In containerized environments, setting -Xmx too close to the container limit can still cause out-of-memory problems because the process needs non-heap memory too.
A safer approach is to leave room for:
- thread stacks
- metaspace
- native memory
- monitoring agents
Comparisons
Heap-related JVM options compared
| Option | Meaning | What it controls | Typical use |
|---|---|---|---|
-Xms | Initial heap size | Heap size at JVM startup | Set starting memory |
-Xmx | Maximum heap size | Upper heap limit | Prevent uncontrolled growth |
-Xss | Thread stack size | Memory per thread stack | Tune deep recursion or many threads |
-XX:InitialHeapSize | Internal JVM flag equivalent to -Xms | Initial heap size | Advanced inspection/config |
-XX:MaxHeapSize | Internal JVM flag equivalent to -Xmx | Maximum heap size | Advanced inspection/config |
-Xms vs -Xmx
| Feature | -Xms | -Xmx |
|---|---|---|
| Meaning | Initial heap size | Maximum heap size |
| Used at startup | Yes | Yes |
| Can affect runtime growth | Indirectly | Yes |
| Common value style | Smaller or equal to -Xmx | Equal to or larger than -Xms |
| If set equal | Fixed heap startup and cap | Same fixed heap startup and cap |
Equal values vs different values
| Strategy | Example | Benefit | Trade-off |
|---|---|---|---|
| Equal values | -Xms512m -Xmx512m | Predictable behavior | Reserves more memory immediately |
| Different values | -Xms256m -Xmx1g | Lower startup memory use | Heap may need to grow later |
Default values vs explicit values
| Approach | Benefit | Risk |
|---|---|---|
| Let JVM choose | Simpler, adaptive | Harder to predict exactly |
| Set explicitly | Predictable and repeatable | Can be misconfigured |
Cheat Sheet
Quick reference
java -Xms256m -Xmx1g MyApp
-Xms= initial heap size-Xmx= maximum heap size
Units
k= kilobytesm= megabytesg= gigabytes
Examples:
-Xms128m
-Xmx2g
Key rules
-Xmsshould usually be less than or equal to-Xmx-Xmxlimits heap growth- JVM defaults are not universal constants
- actual defaults depend on JVM version and environment
- process memory can exceed
-Xmxbecause of non-heap memory
Useful commands
Check selected heap values:
java -XX:+PrintFlagsFinal -version
Filter relevant flags on Unix-like systems:
java -XX:+PrintFlagsFinal -version | grep -E "InitialHeapSize|MaxHeapSize"
Java runtime methods
Runtime runtime = Runtime.getRuntime();
runtime.maxMemory(); // close to -Xmx
runtime.totalMemory(); // current allocated heap
runtime.freeMemory(); // free space in current allocated heap
Common setups
-Xms512m -Xmx512m # fixed heap
-Xms256m -Xmx2g # grow as needed
Edge cases
- Too small
-Xmx->OutOfMemoryError - Too large
-Xmx-> memory pressure on host/container - In containers, leave room for non-heap memory
FAQ
What does -Xms mean in Java?
-Xms sets the initial heap size for the JVM when the program starts.
What does -Xmx mean in Java?
-Xmx sets the maximum heap size the JVM is allowed to use.
What are the default values of -Xms and -Xmx?
They do not have one universal fixed value. The JVM usually calculates them from the environment, Java version, and available memory.
How can I check the actual default heap size used by my JVM?
You can inspect JVM flags with:
java -XX:+PrintFlagsFinal -version
Look for InitialHeapSize and MaxHeapSize.
Is -Xmx the total memory used by the Java process?
No. It only limits heap memory. The process also uses non-heap memory such as metaspace, stacks, and native memory.
Should -Xms and -Xmx be the same?
Sometimes. Setting them equal can make memory behavior more predictable, especially for server applications. But it also reserves more memory up front.
Can I omit both options?
Yes. The JVM will choose defaults automatically. This is common in development, but production systems often set them explicitly.
What happens if I set -Xmx too low?
Your application may fail with java.lang.OutOfMemoryError: Java heap space if it needs more heap than the limit allows.
Mini Project
Description
Build a small Java program that prints the JVM heap settings visible at runtime. This project helps you connect command-line JVM options to what your Java program can observe while it is running. It is useful because many developers need to verify memory settings in local development, servers, and containerized deployments.
Goal
Create a Java program that reports the current heap size, free memory, and maximum heap size, then run it with different -Xms and -Xmx values to observe the difference.
Requirements
- Create a Java class with a
mainmethod. - Print the current allocated heap, free heap, and maximum heap in megabytes.
- Run the program once without JVM memory flags and once with explicit
-Xmsand-Xmxvalues. - Compare how the reported numbers change between runs.
Keep learning
Related questions
Add External JAR Files to an IntelliJ IDEA Java Project
Learn how to add external JAR dependencies to an IntelliJ IDEA Java project using module libraries, and when to use Maven or Gradle instead.
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Call a Method After a Delay in Android Java
Learn how to run Java code after a delay in Android using Handler.postDelayed, manage the main thread, and cancel callbacks safely.