Get to know essential JVM (Java Virtual Machine) options for better performance and debugging.

If you are a Java developer or middleware administrator, then you should know what JVM options mean along with their importance, and how they impact your application. Let’s find out them.

JVM Options Overview

Talking about JVM options, then there are three types of options that you can include to your JVM, standard, non-standard, and advanced options. If you try an advanced option, you always use the option with -XX . Similarly, if you’re applying a non-standard option, you use -X . Standard options don’t prepend anything to the option.

Which JVM options are used by your application?

If the application is running on Linux, you can use ps -ef | grep java  to identify the Java process and look at the JVM options printed as process arguments. If more than one Java process is going on the system, then you may require to go with a keyword that is unique to your Java application.

If your argument is too long, then try using ps -auxww as this command will also show a long argument list as well.

After having a list of JVM flags, you can get an idea about the behaviors of any Java application, e.g., Tomcat.

Java heap size

 -Xms - set initial Java heap size
 -Xmx - set maximum Java heap size
 -Xss - set java thread stack size

-Xms – This option is to define starting heap size for JVM, e.g.,Xms2048m which means an initial heap size of JVM is 2 GB around. So, when a JVM starts, the heap memory will be this much big. Surprisingly yes! This is carried to prevent resizing during startup and enhance the startup time of JVM.

-Xmx – This option is to define the maximum heap size of JVM, e.g.,Xmx2048m which means the maximum heap size of JVM will be 2 GB only.

You will essentially always have-Xmsand-Xmx together.

Set Percentage of the heap

-XX:MaxHeapFreeRatio – sets the maximum percentage of heap free after GC to avoid shrinking.

-XX:MinHeapFreeRatio – sets the minimum percentage of heap free after GC to avoid expansion; to monitor the heap usage, you can use JCosole.

Enable class data sharing

Specify Xshareclasses option to enable class data sharing in a shared class cache. The JVM connects to an existing cache or creates a cache if one does not exist. You can have multiple caches, and you can specify the correct cache by adding a suboption to the -Xshareclasses option.

PermGen Size

Earlier JVM options define the size of heap memory but -XX:PermSize is to define the size of PermGen space, where the string pool and class metadata is saved. This option is particularly effective for a web server like Tomcat, which often loads classes of the web application during deployment.

By the way, It’s worth realizing that PermGen space is taken over by Metaspace in Java 8, and this option is not applicable if you are running with JRE 8 JVM.

Print GC

-verbose:gc - logs garbage collector runs and how long they're taking. 
-XX:+PrintGCDetails - includes the data from -verbose:gc but also adds information about the size of the new generation and more accurate timings.
-XX:-PrintGCTimeStamps - Print timestamps at garbage collection.

These JVM options are used to enable the garbage collection logging, which is highly effective for the latency-sensitive operation. We used to be on systems where we seek for microsecond latencies, and if you recognize, a big garbage collection can last several milliseconds.

So, we go for GC free architecture like LMAX disruptor, but indeed if you are not going for ultra latency-sensitive application, this handy option will advise you important GC statistics. It will get you whether it’s big or minor garbage collection, which kind of garbage collector is applied, how often memory is restored, and how much time it held, etc.

Handling ‘OutOfMemory’ Error

To trigger heap dump on out of memory, you can use -XX:+HeapDumpOnOutOfMemoryError

This JVM option produces a stack dump when your JVM dies with OutOfMemory Error. There is no expense involved unless an OOM really occurs. This flag is a requisite for production systems as it is usually the only way to determine the problem deeply.

The heap dump will be set up in the “current directory” of the JVM by default. If you wish to create heap dumps on specific directory, then run

-XX:HeapDumpPath= [path-to-heap-dump-directory]
-XX:+UseGCOverheadLimit
-XX:OnOutOfMemoryError="< cmd args >;< cmd args >"

The heap dump file can be huge in size, up to gigabytes, so assure that the target file system allows sufficient capacity.

If we want to restart the server immediately after out of memory occur, then we can set this parameter of the same purpose –

XX:OnOutOfMemoryError="shutdown -r"

Trace classloading and unloading

-XX:+TraceClassLoading and -XX:+TraceClassUnloading are two JVM options that we use to print logging information whenever classes loads into JVM or unload from JVM. These JVM flags are useful if you have any type of memory leakage linked to classloader and suspecting to it that classes are not unloading or garbage collected.

Java classpath

Talking about JAVA Classpath then-Xbootclasspath specifies classpath entries we want loaded without verification. The JVM verifies all classes it loads to ensure that it don’t try to dereference an object with an int, pop of extra entries off the stack or push too many, and so on. 

Putting class on the bootclasspath skips the cost as well, but should only be used when you know that the classes have been verified many times before. In JRuby, this reduced startup time by half and more for a simple script.

Profiling

Java Profiling is the process of monitoring various JVM levels parameters such as Method Executions, Thread Executions, Garbage Collections, and Object Creations. Java Profiling provides you with a finer view of your target application execution and its resource utilization, as well.

-Xprof 
-Xrunhprof

64-bit environment

In the OS environment where both 32 and 64-bit packages are installed, the JVM automatically chooses 32-bit environmental packages as default.

If we want to set the environment to 64 bit manually, we can do so using -d<OS bit> parameter. And obviously, the OS bit can be either 32 or 64.

Conclusion

I hope this helps you to configure JVM parameters for your application. If you are interested in learning in-depth about java memory management, then check out this Udemy course.