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:
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();
runtime.freeMemory();
System.out.println( + maxMemory / ( * ) + );
System.out.println( + totalMemory / ( * ) + );
System.out.println( + freeMemory / ( * ) + );
}
}
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 near at startup.
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
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.
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 |
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:
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.
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
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.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.
Convert a Java Stack Trace to a String
Learn how to convert a Java exception stack trace to a string using StringWriter and PrintWriter, with examples and common mistakes.