Welcome to the tenth RebelLabs cheat sheet! This time we’ll focus on the useful JVM options you might want to use, but forget about. In this post, we’ll describe what each of the featured options do. But first, let’s look back at all ten of our cheat sheets, which we started way back in Dec 2015!
- Java 8 Best Practices
- Java 8 Streams
- Git Commands
- Docker Commands
- Java Collections
- Spring Framework Annotations
- Java Generics
- JVM Options
Wow, what a colorful journey! Here’s an amazing fact for you. If you printed out all our cheat sheets and laid them out end to end, you’ve probably got too much time on your hands and I’d recommend finding yourself a hobby. Without further ado, click on the button below and print out the cheat sheet so you don’t have to keep all those pesky options in your head!
So let’s begin with a top down view. There are three types of options that you can add to your JVM, standard, non-standard and advanced options. If you apply an advanced option you always precede the option with
-XX:. Similarly if you’re using a non-standard option, you’ll use
-X. Standard options don’t prepend anything to the option. I can tell you’re already impressed by the consistency at play here. Let’s start with the standard options.
If you wanted to get a full list of the standard options at the command line, simply type
java without further parameters and you’ll see the usage statement followed by a wealth of standard options. For this cheat sheet, we’ve picked a few out that we find most interesting.
First of all, we’ll start with the common system property. This can be set on JVM creation like so:
-D flag states that the following name value pair should used as a system property within the JVM and can be programmatically retrieved as follows:
The same system property could be created programmatically after the JVM has been created with the following code:
At ZeroTurnaround, we simply love java agents! So much in fact, we’ve added them to all our products, from JRebel to XRebel, from JRebel for Android to XRebel Hub! A java agent is like a JVM plugin, that utilizes the
Instrumentation API. Interesting manipulations of bytecode can be achieved which can lead to many amazing tools. To add a java agent, simply point to the path of the jar file that contains the agent code and manifest, as shown below.
If you need more information about the inner workings of your JVM during runtime you can make use of the
-verbose option. You can use it in a number of flavors to gather information in different areas. These can include information about loaded classes (
class), garbage collection (
gc) and JNI (
jni) activity. In the example below we’re getting verbose information about garbage collection activities. All additional information is sent to the standard output log.
Like standard options, you’re able to retrieve the full list of non-standard options from the command line by calling java
When the JVM starts, it uses a default bootstrap class path to search for bootstrap classes and resources. To override the default bootstrap class path, supply a list of paths and/or archives to the following JVM option.
You can also append or prepend the default bootstrap classpath by using commands
Are you fed up with your GC events being logged to standard out? Yes? Then this option is for you! Set the
-Xloggc option and supply a filename and you’re logging to whichever file you like! This option overrides the
-verbose:gc option that was introduced in the last section.
The best way to avoid your JVM falling over in a heap, is to intentionally start out with a heap from the beginning! The question is, how big should that heap be? Well, it realistically depends on your applications and what you intend to do with your JVM. You should also look to change your heap sizes, measure and repeat before settling on a final size. You can set both the initial and max size of your heap in bytes, using the usual
g notation we’re probably all used to. The example JVM options below will start the JVM up with an initial 1 GB heap size, and allow it to grow up to a maximum of 8 GB if needed.
To disable garbage collection of classes, you can use the following option below. This can save you time during garbage collection, as only objects are eligible to be garbage collected. Of course there is an increased risk of running out of memory, particularly if you’re on a version of Java that uses a permanent generation space.
The final non-standard option we’ll talk about is one that allows you to profile your running JVM. Of course it won’t be as fully featured or easy to understand as those profilers with nice UIs, such as XRebel (yeh, yeh cheap plug!). However, it’s very easy to enable with the following option. All information goes to the standard output.
This cheat sheet is brought to you by XRebel, a tool to remind you about your app performance when you are actually working on it, not later when your clients think it is already slow. If you're working with any Java web applications, you should try it. It might change your attitude towards performance. Try XRebel!
We’ll start around the topic of garbage collection. In Java 9 the standard garbage collector will be Garbage First Garbage Collector (G1GC), although you can enforce any of the garbage collection strategies by electing to use them. These might include the Concurrent Mark Sweep (CMS) garbage collector, the parallel scavenge garbage collector, the serial garbage collector and of course G1GC. You can enable each by using the following options. Needless to say, don’t try and use multiple GC options for the same runtime!
-XX:+UseConcMarkSweepGC -XX:+UseParallelGC -XX:+UseSerialGC -XX:+UseG1GC
The Flight Recorder feature is built into the JDK. It allows you get retrieve detailed information about how your application and the JVM itself are performing. It works as you would expect a profiler to function and collects event information for you to examine. In order to enable this functionality, you also need to unlock the commercial features of the JVM with a separate JVM option. Both of these options are shown below.
If you would like to see your error data in a specific file, you may use the option below with the filename of the log file you wish to use. Now you can populate your nice clean log file with all your amazing errors!
There’s nothing more frustrating than when you try to debug an error without debug information. A good example of this is the familiar
OutOfMemory error. This event will bring your JVM to its knees with next to no information as to why. There is help out there if you use this next option. The
HeapDumpOnOutOfMemory option will give you a .hprof file that providing you with loads of debug information. You could open this file in Eclipse MAT or whatever tool you prefer and work out what is hogging your heap. It’s so detailed you can diagnose the problem right down to the very last object and primitive you might be leaking.
If you’re desperate to understand when your garbage collector is doing its job, but don’t want the full verbosity of
-verbose:gc, try the
PrintGC option. It will simply print a message out every time a garbage collection event is performed.
Are you curious when or if your classes are being loaded? If so, you might want to check out the next option. This option enables the tracing of every class loaded by the JVM. Helpful, if you’re into that kind of thing.
Before everyone writes in and complains, yes I know the permanent generation was removed from Java 8! However, if you’re not quite cool enough to be using the latest version you may find this next option useful. If you have problems with a small permgen space then you’ll definitely find it useful!. You can change the max size of the permgen in a similar way to how you might change the size of the old generation heap. Just provide the number of bytes you’d like to use as your max size, as we have below.
Did you know that the memory in your thread stack spaces are not allocated from the heap and are therefore not affected when you use the
-Xmx options. If you wanted to increase, or maybe even reduce the size of your thread stack spaces, you can do so by specifying the number of bytes like so.
An interesting option that was available pre-Java 8 is the
UseStringCache option. This allows the JVM to cache commonly used Strings. However, it was unfortunately removed from Java 8 with no replacement, so you have to be on an earlier version to make use of this.
If you’re using the G1GC you should become familiar with region sizes and understand what’s best for your application. As with all options like this, try out different values, measure and repeat. In the future when G1GC becomes the standard in Java 9, you’ll need to be best friends with it.
-Xmx settings we mentioned earlier are applicable to the old generation heap only. In most JVMs, the Java heap space also contains a young generation, or nursery heap. To update the max size of the young generation, use the following option.
If you want to make your JVM performance really angry and thirsty for a fight, you can enable the aggressive performance optimization features of the JVM as follows.
In this post, we covered some of the popular and interesting options available at the command line for Java. For the complete list of Java 8 options, be sure to look at the official documentation from Oracle. Remember when making changes to your options to test, measure and iterate to make sure you’re tuning your JVM correctly, particularly around heap sizes. Be sure to download and print out this cheat sheet!