Question

JVM Heap Size Explained: What -Xms and -Xmx Mean in Java

javamemory-managementparametersjvm

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.

  • -Xms is the size of the warehouse when the business opens.
  • -Xmx is 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:

  • -Xms controls the starting space
  • -Xmx controls the upper limit

The JVM acts like a warehouse manager that tries to choose sensible defaults when you do not provide them yourself.

Take Quiz

Syntax and Examples

Basic syntax

java -Xms<size> -Xmx<size> MyApp

Common size suffixes:

  • k = kilobytes
  • m = megabytes
  • g = 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 -Xmx
  • totalMemory() is the heap currently allocated, often starting near -Xms
  • freeMemory() 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

  1. The JVM starts.
  2. It reads -Xms64m, so it begins with about 64 MB of heap.
  3. It reads -Xmx256m, so it may expand the heap up to about 256 MB if needed.
  4. The main method runs.
  5. Runtime.getRuntime() returns an object that gives information about the JVM runtime.
  6. runtime.maxMemory() returns the maximum heap limit, which is typically near 256 MB.
  7. runtime.totalMemory() returns the amount of heap currently allocated, typically near 64 MB at startup.
  8. 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 now
  • maxMemory() = 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.

Take Quiz

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

OptionMeaningWhat it controlsTypical use
-XmsInitial heap sizeHeap size at JVM startupSet starting memory
-XmxMaximum heap sizeUpper heap limitPrevent uncontrolled growth
-XssThread stack sizeMemory per thread stackTune deep recursion or many threads
-XX:InitialHeapSizeInternal JVM flag equivalent to -XmsInitial heap sizeAdvanced inspection/config
-XX:MaxHeapSizeInternal JVM flag equivalent to -XmxMaximum heap sizeAdvanced inspection/config

-Xms vs -Xmx

Feature-Xms-Xmx
MeaningInitial heap sizeMaximum heap size
Used at startupYesYes
Can affect runtime growthIndirectlyYes
Common value styleSmaller or equal to -XmxEqual to or larger than -Xms
If set equalFixed heap startup and capSame fixed heap startup and cap

Equal values vs different values

StrategyExampleBenefitTrade-off
Equal values-Xms512m -Xmx512mPredictable behaviorReserves more memory immediately
Different values-Xms256m -Xmx1gLower startup memory useHeap may need to grow later

Default values vs explicit values

ApproachBenefitRisk
Let JVM chooseSimpler, adaptiveHarder to predict exactly
Set explicitlyPredictable and repeatableCan be misconfigured
Take Quiz

Cheat Sheet

Quick reference

java -Xms256m -Xmx1g MyApp
  • -Xms = initial heap size
  • -Xmx = maximum heap size

Units

  • k = kilobytes
  • m = megabytes
  • g = gigabytes

Examples:

-Xms128m
-Xmx2g

Key rules

  • -Xms should usually be less than or equal to -Xmx
  • -Xmx limits heap growth
  • JVM defaults are not universal constants
  • actual defaults depend on JVM version and environment
  • process memory can exceed -Xmx because 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.

Take Quiz

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 main method.
  • Print the current allocated heap, free heap, and maximum heap in megabytes.
  • Run the program once without JVM memory flags and once with explicit -Xms and -Xmx values.
  • Compare how the reported numbers change between runs.
Take Quiz

Keep learning

Related questions

View more