Thursday, April 27, 2023

Difference between -Xms and -Xmx JVM Parameters forJava Heap Memory

Though both -Xms and -Xmx JVM options are used to specify the size of heap memory, main difference between them is that -Xms is used to specify initial heap memory while -Xmx is used to specify the maximum heap memory. The JVM (Java virtual Machine) provides several command line arguments to specify size of different memory areas, also known as generations of Java Heap space, but two of the most useful JVM parameters which specify initial and maximum heap memory is -Xms and -Xmx. When you start JVM by using java command you can specify the maximum heap size with the JVM option -Xmx and a size e.g. java -Xmx1G MainClass will start JVM with maximum heap size of 1 giga bytes. Remember there is no space between -Xmx and size, if you leave space e.g. -Xmx 1024M then JVM will throw invalid heap memory error, so be careful there. 

The JVM also allows you to use suffixes like G for giga bytes, M or mega bytes and K for kilo bytes to specify size of heap memory with both -Xms and -Xmx. The big question is what size you specify? how do you know how much memory is needed by your Java application? Well for that you need to profile your application or you can also take an educated guess depending upon requirement. 

Anyway, GC and memory tuning is an art and you should read Java Performance the definitive guide to learn more about this art. This book provides process, commands, profilers and tools to take sample and analyze them to find potential memory problem and improve performance of Java application. 


What is initial and maximum heap memory in Java JVM?

Before you start using -Xms and -Xmx command line arguments, let's take a step back and learn little bit about initial and maximum heap memory in JVM. When you start the JVM by executing java command, it ask some memory from host operating system where it is running e.g. Windows or Linux.

You can tell your application how much memory to ask by using -Xms parameter, but since it's not mandatory and many programmer doesn't specify it, Java also uses a default value for initial memory, which varies from machine to machine. It depends upon how much physical memory your host has and other factors e.g. 32-bit or 64-bit JVM

The maximum heap memory as name suggests is the maximum your program can have. JVM might have asked even more memory from operating system but some of them is used by itself. 

Similar to initial heap memory, JVM also uses default value for maximum heap size which varies between hosts, operating system and different versions of JVM as discussed in my earlier post about frequently asked questions on heap memory. 

When you specify -Xmx then JVM use that number but it doesn't allocate that much memory at start, in fact it grows till that number and before expanding heap space, it does excessive garbage collection to free-up some space. 

It only grows if it couldn't free up required space needed for object allocation and it can only grow upto maximum heap, if there is no head room then it throws java.lang.OutOfMemoryError: Java heap space




Important points about -Xms and -Xmx JVM Option for Heap Memory Setting

Now, you know that what is initial and maximum heap memory and how to resize them using -Xms and -Xmx options, let's revise some important points about these two important JVM paramters. 

1) If both -Xms and -Xmx has same value then JVM will ask the host operating system for that full memory allocation on startup and it will not grow any larger. Potentially avoiding frequent garbage collection it does before increasing size of heap memory in case -Xms is not specified or smaller than -Xmx value. 

2) If you don't specify the command line arguments -Xms and -Xmx then JVM uses the default vlaue for initial and maximum heap memory. For the initial memory allocation, the default value is 1/64 of the memory on host, up to 1GB, and for maximum heap memory , it is smaller of 1GB and 1/4th of host's physical memory. 

3) It's advisable to specify JVM option -Xms if you know that your application will need a certain amount of memory e.g. to build the cache, as it will save your Java application from excessive slow garbage collections before JVM expands to the reuqired size. 

4) From experiments, it's advised that ideal ratio for -Xms to -Xmx is either 1:1 to prevent any GC during memory growth or 1:1.5 to have some head room when absolutely needed. 

Difference between -Xms and -Xmx JVM Parameters forJava Heap Memory


5) You cannot specify any arbitrary value to -Xms and -Xmx they are subject to whether you are running on 32-bit JVM or 64-bit JVM, supplying an invalid value will result in invalid heap size error. The theoretical limit of maximum heap memory for 32-bit JVM is 4GB but practical limit is way less than that and depends upon which operation system you are running your Java application. 

Windows allows only around 1.5G and Linux can go upto 2.5GB, see this article to learn more about maximum heap size on different JVM and operating system combination. 

6) Apart from these, you can also use -Xss to specify the size of Stack memory of Threads in Java. This is rarely used in compared to -Xms and -Xmx, and you should only adjust if you are facing lots of StackOverFlowError. 

7) It's also worth noting that Xms and Xmx is different from -XX:PermSize and -XX:MaxPermSize which is used to specify size of permanent generation to avoid java.lang.OutOfMemoryError:Permgen Space. Permanent generation, also known as Meta space from Java 8 onwards, is outside of heap and used to store class metadata and String pool until JDK 7.  As I said, It is also removed in Java 8 and a new memory area called MetaSpace is introduced which lives on native memory. 

That's all about difference between -Xmx and -Xms JVM parameters in Java. Though both are used to resize heap memory, one is used to specify initial heap size and other is used to specify the maximum heap size. Point to remember is that JVM will not start with the maximum heap memory, in fact it grows till that memory and before expanding memory it does excessive slow garbage collection, which can potentially slow down your Java application. 

To avoid that, you should specify both initial and maximum heap memory depending upon how much memory is required by your Java application. If you don't know much just set them of same size, this will at least prevent excessive GC done by JVM before expanding heap memory.


Thanks for reading this article so far. If you like my explanation of JVM options -Xms and -Xmx in setting heap size in Java then please share this article on Facebook and Twitter or LinkedIn. If you have any doubt, feel free to ask questions on comments and if you want to learn more, you can also checkout these Java books and Java performance courses for further learning

No comments:

Post a Comment