10 Essential JVM Options for a Java Production System

Hello guys, this is a brief guide of appropriate JVM options, which you will often see in production Java systems. As a Java developer, you should know what these JVM options mean, their importance, and how they affect your application. You will find that most of the JVM options are related to heap memory, garbage collection and to log some details, like heap dump, necessary for troubleshooting heap related issues like a memory leak or excessive memory consumption. It's Ok if you don't know these Java virtual machine options yet, but you should be familiar with them, and that's the objective of this article. Btw, how do you find the JVM options your application is using? Well, you can see the startup scripts through which your application is started.

Alternatively, if your application is running on Linux, you can do ps -ef | grep java to find the Java process and see the JVM options printed as process arguments. If more than one Java process is running on the system, then you may need to search with a keyword that is unique to your Java application.

Remember, your process might not catch with ps -ef, if the argument list is too long, so you can also try using ps -auxww command, which shows the process with a long argument list as well.  I know these are Linux commands but didn't I said that Linux is an excellent tool in the arsenal of any developer.

Once you have that list of JVM flags, you can understand certain behaviors of any Java application, like Tomcat, particularly how much memory is left to grow, etc.

Btw, this is not the guide for JVM performance tuning, it will just let you familiar with essential JVM options from Java developer's perspective. If you want to learn JVM tuning in-depth, you should refer to the Java Application Performance and Memory Management course by Matt  GreenCroft on Udemy.

This is a great course to learn things like how to take heap dump and analyze them to find memory-related problems along with many coding tips, JVM options, benchmarking with JMH, and even GrallVM for better Java application performance.




Top 10 JVM options for Java Developers

Here is my list of essential JVM options, which are a must for any production system, and I strongly believe that every Java developer should be familiar with these Java virtual machine flags.

The list is not big, and it just includes the most popular options. It doesn't include JVM options related to 32-bit or 64-bit or something like -XX: UseCompressedOOP, which is quite essential for a 64-bit Java virtual machine.


1) -Xms

This option is to specify starting heap size for JVM, like Xms2048m which means an initial heap size of JVM is 2GB. When JVM starts, the heap memory will be this big. This is done to prevent resizing during startup and improve the startup time of JVM.


2) -Xmx

This option is to specify the maximum heap size of JVM, e.g., Xmx2048m means a maximum heap size of JVM will be 2GB. You will almost always see -Xms and -Xmx together. Their ration is also important; the ration of 1:1 or 1:1.5 is found to be more efficient.

You must specify sufficient heap space for your Java application to avoid java.lang.OutOfMemoryError: Java Heap space, which comes if there is not enough memory to create new objects or arrays.



3) -XX:PermSize

Earlier JVM options specify the size of heap memory, but this one is to specify the size of PermGen space, where string pool and class metadata is stored. This option is critical for a web server like Tomcat, which often loads classes of the web application during deployment.

Btw, It's worth knowing that PermGen space is replaced by Metaspace in Java 8, and this option is not relevant if you are running with JRE 8 JVM.

If you are interested in further learning, you can also check the Java Memory Management course on Udemy to learn more about JVM memory architecture and how to tune them properly.

Useful JVM memory options



4) -XX:MaxPermSize

This is the counterpart of the earlier JVM option and used to specify the maximum size of the permanent generation of JVM. The permgen will expand until it reaches this value, It cannot expand beyond this.

If the permanent generation of JVM is full, then you will get java.lang.OutOfMemoryError: PermGen space. So, this option is vital to avoid that error, but only if you are running in Java 7 or a lesser version. After Java 7, this option is deprecated.



5) -verbose:gc

This JVM option is used to enable Garbage collection logging in your Java application, which is very important for the latency-sensitive application. I used to work on systems where we strive for microsecond latencies, and if you remember, a major garbage collection can last several milliseconds.

So, we strive for GC free architecture like LMAX Disrupter, but even if you are not working for ultra latency-sensitive application, this handy option will tell you important GC statistics.

It will show you whether it's major or minor garbage collection, which kind of garbage collector is used, how much memory is reclaimed, and how much time it took, etc.

If you want, you further join Understanding the Java Virtual Machine: Memory Management course on Pluralsight to learn more about memory management, Garbage collection, and JVM tuning from experts.
Useful JVM garbage collection options.

This is a series of classes on JVM, which provides comprehensive learning on JVM internals and Java performance tuning, including security and classloading.

6) -XX:+PrintGCTimeStamps

This JVM option will prepend record with timestamp since Java application starts so you can see that at which state of your application GC activity peaks.


7) -XX:+PrintGCDetails 

Prints some more garbage collections details.


8) -Xloggc:[path to gc log file]

You can log all garbage collection details into a log file for future analysis using this JVM option. You can later use tools like GCViewer to analyze the logs files.



9) -Dsun.net.inetaddr.ttl=

This is an essential JVM option if your Java program connects to the database or any other Java processor web server via a load balancer, like in which hostname can be routed to the different IP addresses in case of failover.

This option specifies the number of seconds during which the DNS record will be cached in JVM. This is even more important with Java 6 virtual machine, which caches the IP address forever.

In that case, you don't have other option but to restart your Java application if upstream or database switched to the secondary node, not the most elegant option.



10) -XX:+HeapDumpOnOutOfMemoryError

This JVM option creates a heap dump when your JVM dies with OutOfMemory Error. There is no overhead involved unless an OOM actually occurs. This flag is a must for production systems as it is often the only way to further analyze the problem.

The heap dump will be generated in the "current directory" of the JVM by default. If you want to create heap dumps on specific directory then use -XX:HeapDumpPath=[path-to-heap-dump-directory] e.g. -XX:HeapDumpPath=/dsk3/dumps.

Remember that the heap dump file can be huge, up to Gigabytes, so ensure that the target file system has enough space. You can also refer to Java Performance Companion 1st edition by Charlie Hunt to learn more about analyzing heap dump and thread dump in Java.


It is the most up-to-date book in Java performance to date and helps you to squeeze the best performance with JDK 8 in any application.

That's all in the least of essential JVM options must for a Java production system. As I said, every Java developer should be familiar with these options and should not put the Java application into production without having these JVM options.

You may need to put more JVM options, like to select a garbage collector, like ConcurrentMarkSweep or G1 and other network-related parameters, but this is a bare minimum set of JVM options for any production Java system.

Btw, this list is no more a comprehensive list and only covers most common and essential JVM options, For a more detailed list of JVM options, you can check the following resources.

Further Learning
Java Memory Management
Understanding and Solving Java Memory Problems 

Related Java and JVM tutorials for Java programmers
  • The 2020 Java Developer RoadMap (guide)
  • 10 Things Java Developer Should learn in 2020 (goals)
  • Top 5 Courses to learn JVM Internals and Memory (courses)
  • What is the difference between JRE, JDK, and JVM in Java? (answer)
  • How do you find if JVM is 32-bit or 64-bit? (answer)
  • Top 5 Advanced Java Courses for Programmers (courses)
  • When is a class loaded and initialized in JVM? (answer)
  • Top 5 Courses to become a full-stack Java Developer (courses)
  • What is the difference between Stack and Heap Memory in JVM? (answer)
  • 10 Advanced Core Java courses for Programmers (courses)
  • 10 Tips to become a better Java developer (tips)
  • What is the difference between Oracle HotSpot JVM and IBM  JVM? (answer)
  • 5 Books to Learn Java Performance Tuning (list)
  • What is the maximum heap size of 32-bit and 64-bit JVM on Windows and Linux? (article)
  • 10 Free Java Courses for Programmers (courses)
Thanks for reading this article so far. If you find these JVM options useful then use them in your project and don't forget to share it with your friends and colleagues. If you have any questions or feedback, then please drop a note.

P. S - If you are serious about learning Advanced Java skills, particularly on writing high-performance Java application then I highly recommend you to check out Java Multithreading, Concurrency, and Performance Optimization by Michael Pogrebinsky on Udemy.  It's an amazing course and also very affordable you can get in just $10 on Udemy sales.

2 comments:

  1. Nice article, but actually sun.net.inetaddr.ttl is NOT a system property, it's a security property. You cannot change the value with a -D option afaik.

    ReplyDelete
  2. There're also some options out there that allow you to specify the GC strategy, depending on the performance requirements.

    ReplyDelete