Update: This answer was originally written in 2014 and is obsolete.

Peter 's answer is correct in that -Xms is allocated at startup and it will grow up to -Xmx (max heap size) but it's a little misleading in how he has worded his answer. (Sorry Peter I know you know this stuff cold).

Setting ms == mx effectively turns off this behavior. While this used to be a good idea in older JVMs, it is no longer the case. Growing and shrinking the heap allows the JVM to adapt to increases in pressure on memory yet reduce pause time by shrinking the heap when memory pressure is reduced. Sometimes this behavior doesn't give you the performance benefits you'd expect and in those cases it's best to set mx == ms. OOME is thrown when heap is more than 98% of time is spent collecting and the collections cannot recover more than 2% of that. If you are not at max heaps size then the JVM will simply grow so that you're beyond that boundaries. You cannot have an OutOfMemoryError on startup unless your heap hits the max heap size and meets the other conditions that define an OutOfMemoryError.

For the comments that have come in since I posted. I don't know what the JMonitor blog entry is showing but this is from the PSYoung collector.

size_t desired_size = MAX2(MIN2(eden_plus_survivors, gen_size_limit()),
                           min_gen_size());

I could do more digging about but I'd bet I'd find code that serves the same purpose in the ParNew and PSOldGen and CMS Tenured implementations. In fact it's unlikely that CMS would be able to return memory unless there has been a Concurrent Mode Failure. In the case of a CMF the serial collector will run and that should include a compaction after which top of heap would most likely be clean and therefore eligible to be deallocated.

Answer from Kirk on Stack Overflow
Top answer
1 of 6
33

Update: This answer was originally written in 2014 and is obsolete.

Peter 's answer is correct in that -Xms is allocated at startup and it will grow up to -Xmx (max heap size) but it's a little misleading in how he has worded his answer. (Sorry Peter I know you know this stuff cold).

Setting ms == mx effectively turns off this behavior. While this used to be a good idea in older JVMs, it is no longer the case. Growing and shrinking the heap allows the JVM to adapt to increases in pressure on memory yet reduce pause time by shrinking the heap when memory pressure is reduced. Sometimes this behavior doesn't give you the performance benefits you'd expect and in those cases it's best to set mx == ms. OOME is thrown when heap is more than 98% of time is spent collecting and the collections cannot recover more than 2% of that. If you are not at max heaps size then the JVM will simply grow so that you're beyond that boundaries. You cannot have an OutOfMemoryError on startup unless your heap hits the max heap size and meets the other conditions that define an OutOfMemoryError.

For the comments that have come in since I posted. I don't know what the JMonitor blog entry is showing but this is from the PSYoung collector.

size_t desired_size = MAX2(MIN2(eden_plus_survivors, gen_size_limit()),
                           min_gen_size());

I could do more digging about but I'd bet I'd find code that serves the same purpose in the ParNew and PSOldGen and CMS Tenured implementations. In fact it's unlikely that CMS would be able to return memory unless there has been a Concurrent Mode Failure. In the case of a CMF the serial collector will run and that should include a compaction after which top of heap would most likely be clean and therefore eligible to be deallocated.

2 of 6
10

Main reason to set the -Xms is for if you need a certain heap on start up. (Prevents OutOfMemoryErrors from happening on start up.) As mentioned above, if you need the startup heap to match the max heap is when you would match it. Otherwise you don't really need it. Just asks the application to take up more memory that it may ultimately need. Watching your memory use over time (profiling) while load testing and using your application should give you a good feel for what to need to set them to. But it isn't the worse thing to set them to the same on start up. For a lot of our apps, I actually start out with something like 128, 256, or 512 for min (startup) and one gigabyte for max (this is for non application server applications).

Just found this question on stack overflow which may also be helpful side-effect-for-increasing-maxpermsize-and-max-heap-size. Worth the look.

🌐
Oracle
docs.oracle.com › cd › E19159-01 › 819-3681 › abeii › index.html
Tuning the Java Heap (Sun Java System Application Server 9.1 Performance Tuning Guide)
By default, the JVM grows or shrinks the heap at each GC to try to keep the proportion of free space to the living objects at each collection within a specific range. This range is set as a percentage by the parameters -XX:MinHeapFreeRatio=minimum and -XX:MaxHeapFreeRatio=maximum; and the total ...
Discussions

java - how to choose the jvm heap size? - Stack Overflow
Bring the best of human thought and AI automation together at your work. Explore Stack Internal ... What i usually do concerning the jvm heap size is setting the max value really high to avoid the infamous OutOfMemoryException. However, this strategy (or lack of strategy) doesn't seem to be really smart. :-). My question is how to choose the min ... More on stackoverflow.com
🌐 stackoverflow.com
How do I set Java's min and max heap size through environment variables? - Stack Overflow
For Apache ant, use ANT_OPTS to affect the environment for the JVM that runs /ant/, but not for the things that ant might launch. The maximum heap size you can set depends entirely on the environment: for most 32-bit systems, the maximum amount of heap space you can request, regardless of available ... More on stackoverflow.com
🌐 stackoverflow.com
JVM 1.8 Min and Max Heap Sizes
I have an app that I'm running in a version 1.8 JVM in Windows. I'm setting max and min heap size, but it only seems to actually use the max setting. The min memory allocation is much lower than what I specified and it grows as needed. My memory settings are... -Xms10240m -Xmx10240m That's... More on tek-tips.com
🌐 tek-tips.com
7
0
February 15, 2017
Best values for min-max RAM, Xms & Xmx arguments
Make your Xms ans Xmx the same value, so both 6GB. Unused RAM is bad RAM More on reddit.com
🌐 r/admincraft
12
15
September 20, 2019
🌐
Bell Software
bell-sw.com › blog › guide-to-jvm-memory-configuration-options
List of JVM memory configuration flags
March 14, 2024 - For instance, if you set -XX:MinHeapFreeRatio=40 and -XX:MaxHeapFreeRatio=70, then the generation expands if the free space percentage goes below 40% and contracts if the free space exceeds 70%. Direct byte buffers are used by the JVM to perform native I/O operations. As opposed to non-direct byte buffers stored in the heap, direct ones reside outside the heap and therefore are not affected by heap size ...
Top answer
1 of 6
25

My question is how to choose the min and max values, and the difference between the two (should max-min be small or big?)

Short answer: don't guess, profile your application.

jconsole can give you useful high-level data such as a feeling for the main resident set vs. the transient data that we normally allocate and garbage collect. What you'll see if you look at the memory tab of that display is usually something like a sawtooth. The lower corner of the sawteeth is about where I would normally set the heap minimum whereas I would use the peak or slope of the sawteeth to experiment with a heap maximum. If your teeth are very steep, you might consider a big heap just to delay the garbage collection. However, if they aren't, you could try a smaller heap maximum to see if that might leave more resources for other processes on your machine (for example).

You should also consider the server VM as that will cause different garbage collection behavior.

All that said, you should also use a more detailed tool such as jvisualvm to profile the memory usage of your process. It's possible that you have a memory leak or greedy allocator that you could tune or eliminate. That would completely change your heap needs.

2 of 6
6

You should enable GC logging and check to see where your OOM is ocurring.

-verbose:gc
-Xloggc:gc.log  
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails

You may be experiencing perm space limits, adjust via -XX:MaxPermSize=YYYm

Anyway to answer your question, I start with no minimums and set the maximum relatively high. I then graph the gc log and find out where my stead state is; visually choose an above-average size for the various generations. Read it like a financial chart, you'll want to see good spread in the new generations and a consistent growth and collection in the tenured generation. As mentioned also graph your perm space to make sure you're not constantly increasing.

GC tuning is an art, in no way a science.

🌐
javaspring
javaspring.net › blog › how-do-i-set-java-s-min-and-max-heap-size-through-environment-variables
How to Set Java Min and Max Heap Size via Environment Variables on Your Server — javaspring.net
Minimum Heap Size (-Xms): The initial heap size the JVM allocates at startup. Example: -Xms512m (512 megabytes). Maximum Heap Size (-Xmx): The maximum heap size the JVM can grow to.
🌐
Mike my bytes
mikemybytes.com › 2022 › 11 › 15 › what-happens-when-you-only-limit-the-maximum-heap-size
What happens when you only limit the maximum heap size? | Mike my bytes
November 15, 2022 - By default, the virtual machine ... a specific range. By default, the JVM aims to keep the free space in a generation between 40% and 70%. The respective configuration options are -XX:MinHeapFreeRatio and -XX:MaxHeapFre...
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › java › how-is-the-default-max-java-heap-size-determined
How is the default max Java Heap size determined? - GeeksforGeeks
July 23, 2025 - If a machine has 128 megabytes of physical memory, then the maximum heap size is 64 megabytes, and greater than or equal to 1 gigabyte of physical memory results in a maximum heap size of 256 megabytes.
🌐
DataStax
docs.datastax.com › en › dse › 6.9 › managing › operations › change-heap-size.html
Changing heap size parameters | DataStax Enterprise | DataStax Docs
By default, DataStax Enterprise (DSE) sets the Java Virtual Machine (JVM) heap size from 1 to 32 GB depending on the amount of RAM and type of Java installed. The cassandra-env.sh automatically configures the min and max size to the same value ...
🌐
Oracle
docs.oracle.com › cd › E19159-01 › 819-3681 › abeik › index.html
Heap Tuning Parameters (Sun Java System Application Server 9.1 Performance Tuning Guide)
This range is set as a percentage by the parameters -XX:MinHeapFreeRatio=minimum and -XX:MaxHeapFreeRatio=maximum; and the total size bounded by -Xms and -Xmx. Set the values of -Xms and -Xmx equal to each other for a fixed heap size. When the heap grows or shrinks, the JVM must recalculate ...
🌐
javathinking
javathinking.com › blog › is-it-good-to-set-the-max-and-min-jvm-heap-size-the-same
JVM Heap Size: Should Max and Min Be Set to the Same Value? Performance Impact & Best Practices — javathinking.com
Two of the most fundamental JVM flags for heap configuration are `-Xms` (initial/minimum heap size) and `-Xmx` (maximum heap size). A longstanding debate in the Java community is: *Should these two values be set to the same number?* On one hand, ...
🌐
GeeksforGeeks
geeksforgeeks.org › java › java-program-to-set-minimum-and-maximum-heap-size
Java Program to Set Minimum and Maximum Heap Size - GeeksforGeeks
July 23, 2025 - // import required packages import ... + (r.totalMemory() - r.freeMemory()) / mb); } } ... This command set the minimum size as 64Mb i.e totalMemory()....
🌐
Oracle
docs.oracle.com › cd › E12839_01 › web.1111 › e13814 › jvm_tuning.htm
5 Tuning Java Virtual Machines (JVMs)
Append the letter 'k' or 'K' to the value to indicate kilobytes, 'm' or 'M' to indicate megabytes, and 'g' or 'G' to indicate gigabytes. The example above allocates 10 megabytes of memory to the Nursery heap sizes and 512 megabytes of memory to the minimum and maximum heap sizes for the WebLogic ...
🌐
Oracle
docs.oracle.com › en › java › javase › 17 › gctuning › ergonomics.html
HotSpot Virtual Machine Garbage Collection Tuning Guide
October 20, 2025 - If the throughput and maximum ... can't be met. The minimum and maximum heap sizes that the garbage collector can use can be set using -Xms=<nnn> and -Xmx=<mmm> for minimum and maximum heap size respectively....
🌐
Alvin Alexander
alvinalexander.com › blog › post › java › java-xmx-xms-memory-heap-size-control
How to control Java heap size (memory) allocation (xmx, xms) | alvinalexander.com
January 31, 2026 - The default size is 64M. (The -server flag increases the default size to 128M.) The maximum heap limit is about 2 GB (2048MB). When setting the Java heap size, you should specify your memory argument using one of the letters “m” or “M” for MB, or “g” or “G” for GB.
🌐
Tek-Tips
tek-tips.com › home › forums › software › programmers › languages › java
JVM 1.8 Min and Max Heap Sizes | Tek-Tips
February 15, 2017 - I have an app that I'm running in a version 1.8 JVM in Windows. I'm setting max and min heap size, but it only seems to actually use the max setting. The min memory allocation is much lower than what I specified and it grows as needed. My memory settings are... -Xms10240m -Xmx10240m That's...
🌐
Medium
medium.com › @maheshwar.ramkrushna › understanding-heap-size-and-its-impact-on-java-application-performance-d4c312bbd13c
Understanding Heap Size and its Impact on Java Application Performance | by Ramkrushna Maheshwar | Medium
May 25, 2023 - We recommend increasing the maximum heap allocation to 512 MB or 1024 MB when dealing with discovery ranges equivalent to a class B subnet, or in excess of 30,000 addressable devices.
🌐
IBM
ibm.com › docs › en › sdk-java-technology › 8
Initial and maximum heap sizes
Understanding the operations of the Garbage Collector (GC) helps you set initial and maximum heap sizes for efficient management of the heap.
🌐
Codecurmudgeon
codecurmudgeon.com › wp › 2012 › 05 › java-memory-settings-jvm-heap-size
Java Memory Settings – JVM Heap Size – Code Curmudgeon
I’ve gotten the chance to work with a large variety of java applications on a wide variety of machines as part of my day job at Parasoft and I’ve found some configurations that will make things run better. On a server machine I recommend you set the min and the max to the same (upper) value.