Last week we looked at some of the internals of the Java VM, being the bytecode interpreter and the JIT compiler. This week we’ll look at the some of the JVM command line options that customise how the interpreter and Just in Time compiler operate at runtime.
JVM Options
The defaults for the JVM and HotSpot compiler generally work very well, but occasionally we may want to tinker with some of the options for better performance on our application.
There are three main types of JVM options:
-
Standard: Basic startup options such as
-classpath
,-D
and-verbose
are standard across different HotSpot JVM implementations. You can runjava -help
to get a list of these options. -
-X
: Non-standard options used to configure common HotSpot JVM properties such as heap sizes (-Xmn
,-Xms
and-Xmx
). These options are not guaranteed to be supported on all HotSpot JVM implementations. You can runjava -X
to get a list of these non-standard options. -
-XX
: Advanced options used to configure advanced HotSpot JVM properties. These can change without notice, but if we read the documentation we shouldn’t be caught with our pants down.If you’ve never come across command line options before, they’re very easy to use. When you start up the JVM (or any of the JDK command line tools for that matter), you just add the options between the
java
command and the Java class you want to run. Options are case sensitive, and are separated from each other with spaces.
java -option1 -option2 -option3 Application
As an aside, depending on the version of Java that you’re running, there could be over 1500 command line options! This includes product, experimental, diagnostic and developmental options. Be sure to read the JVM documentation!
Client or Server JVM
One of the standard options we can use is to select either the Client VM or the Server VM. The options are either -client
or -server
. The 64-bit version of the JDK supports only the server VM, so it will ignore the -client
option.
java -server Application
Previously the JVM checked whether the computer was a server class machine. This meant having at least two cores and at least 2GB of RAM. Nowadays even the cheapest computers we can find are server class machines. This is the reason that recent versions of the JVM have removed many of the differences between server and client VMs.
Interpreter
If we want to run the bytecodes in interpreted mode only without any JIT compilation, we can use the -Xint
command line option:
java -Xint Application
Obviously the program is going to run slower because nothing gets compiled. The option is there because it’s been there almost forever. A possible use case is that we may want to do some comparative benchmarking. The chances of using it in a production system are zero.
JIT Compilation
As discussed in last week’s post, the HotSpot JVM contains a just-in-time compiler to improve the performance of a Java program. The HotSpot JVM profiles a running program, and then selectively optimizes those sections that it decides will have the most speed benefit. These are known as hot spots (hence the name HotSpot JVM). These hot spots are compiled into native code on the fly.
The HotSpot JVM contains two JIT compilers, known as C1 (the client compiler) and C2 (the server compiler), which offer different optimization techniques:
-
C1 offers fast, simple optimizations that are relatively inexpensive (in CPU cycles) to do.
-
C2 offers advanced optimizations that need longer profiling and are more expensive to apply.
The default behaviour from Java 8 has been to use both compilers together to perform tiered compilation. The C1 compiler runs first to improve the performance quickly. At the same time, the C2 compiler gathers enough profiling information to do the more advanced optimizations. The generated native code is then stored in the HotSpot JVM code cache from where it can be run when needed.
JIT Compilation Options
The following are some of the most commonly used JIT compilation options:
-
-Xcomp
forces compilation of methods on first invocation. By default, the Client VM performs 1,000 interpreted method invocations and the Server VM performs 10,000 interpreted method invocations to gather profiling information before compilation. The initial interpretation of Java methods before compilation is then completely disabled. This increases performance at the expense of compiler efficiency. -
-Xmixed
executes all bytecode by the interpreter except for hot methods, which are compiled to native code. -
-XX:CompileThreshold=invocations
sets the number of interpreted method invocations before compilation. This overrides the previous mentioned defaults. This option only works when tiered compilation is disabled using-XX:-TieredCompilation
. -
-XX:-TieredCompilation
disables the use of tiered compilation. This option is only supported by the Server VM. By default, it is enabled (-XX:+TieredCompilation
).
Ending Off
In next week’s post, we’ll look at some aspects of the ahead-of-time (AOT) compiler which is available from Java 9 on.
Don’t forget to share your comments and Java experiences.
Stay safe, and I’ll see you next week!
1 thought on “JVM and JIT Command Line Options”
Pingback: The Ahead of Time (AOT) Compiler • 2022 • Incus Data Programming Courses