5 things you didn't know about ...
Command-line flags for the JVM
Fine-tune JVM performance and the Java runtime
This content is part # of # in the series: 5 things you didn't know about ...
This content is part of the series:5 things you didn't know about ...
Stay tuned for additional content in this series.
The JVM is the workhorse behind the Java application functionality and performance that most Java developers take for granted. And yet very few of us truly understand how the JVM does what it does — things like allocating and garbage-collecting objects, spinning up threads, opening and closing files, interpreting and/or JIT-compiling Java bytecode, and more.
Not only does unfamiliarity with the JVM cost you in terms of application performance, but when something goes wrong with the JVM, it can be very difficult to try to fix.
This installment of 5 things introduces a handful of command-line JVM flags that you can use to diagnose and tune the performance of your Java virtual machine.
I can't tell you how many times I've been asked to consult on an
application performance problem, done a quick
grep across the
code, and found what's shown in Listing 1 — the original Java
Listing 1. System.gc();
// We just released a bunch of objects, so tell the stupid // garbage collector to collect them already! System.gc();
Explicit garbage collection is a really bad idea— something
on the order of locking yourself in a phone booth with a rabid pit bull.
Although the exact semantics of the call are implementation-dependent,
assuming your JVM is running a generational garbage collector (which most
of them are),
System.gc(); forces the VM to do a "full sweep"
of the heap, even if one isn't necessary. Full sweeps are typically
several orders of magnitude more expensive than a regular GC operation,
which is just plain bad math.
But don't take my word for it — Oracle's engineers provided us with a
JVM flag for just this particular human-error problem: The
-XX:+DisableExplicitGC flag automatically turns a
System.gc() call into a no-op, giving you the opportunity to
run your code and see for yourself whether
helped or harmed the overall execution of the JVM.
The same function that is provided on the HotSpot technology based JVMs can
be achieved using the
-Xdisableexplicitgc output on the IBM
Have you ever had one of those days where the JVM kept dying on you,
OutOfMemoryErrors, and you couldn't for the life of
you set up the debugger to catch it and see what the problem was? Sporadic
and/or nondeterministic problems like this can drive a developer
What you want at times like these is to catch a snapshot of the heap right
as the JVM is on its dying breath — and that's precisely what the
-XX:+HeapDumpOnOutOfMemoryError command does.
Running this command tells the JVM to take a "heap dump snapshot" and save
it to a file for processing, usually using the
(which I introduced in a previous
article). You can specify the actual path to which the file is saved
using the corresponding
-XX:HeapDumpPath flag. (Regardless of
where the file is saved, make sure the filesystem and/or the Java process
has the necessary permission configuration to be able to write there.)
The IBM JVMs dump engine has this facility enabled by default, ensuring
that you obtain a heapdump if an
OutOfMemoryError occurs. The
IBM dump engine provides a number of configuration options using the
-Xdump command line options, including disabling the
Periodically, it's useful to slip a class into the classpath that is
slightly different from the one that comes with the stock JRE, or that
somehow extends the JRE. (An example would be a new Java Crypto API
provider). If you want to extend the JRE, then your custom implementation
needs to be available to the bootstrap
java.lang.Object and all his buddies in
While you could crack open
rt.jar and slide your
custom implementation or new package into it, that would technically
violate the license you agreed to when you downloaded the JDK.
Instead, use the JVM's own
-Xbootclasspath option, along with
-Xbootclasspath lets you set the complete boot classpath,
which typically has to include a reference to
rt.jar, plus a
bunch of other JAR files that ship with the JDK that aren't part of
-Xbootclasspath/p prepends the value to
the existing bootclasspath, and
If, for instance, you've modified the stock
and put the modifications in a subdirectory,
mods, then a
-Xbootclasspath/a mods parameter will put the new
Integer in front of the default one.
-verbose is a useful first-level diagnostic utility for
virtually any type of Java application. The flag has three sub-flags:
gc, is typically the first place developers go to try to
figure out if the JVM garbage collector is acting up and causing poor
performance. Unfortunately, interpreting
gc's output can be
tricky — enough so that it's been the subject of whole books.
What's worse, the output printed to the command-line can change from one
Java release to another, or from one JVM to another, making it even harder
to correctly interpret.
Generally speaking, if the garbage collector is a generational collector
(which most of the "enterprise-class" VMs are), some kind of visible flag
will appear to indicate a full-sweep GC pass; in the Oracle JVM, the flag
appears as "
[Full GC ...]" at the start of the GC output
class can be a life-saver for trying to diagnose
ClassLoader and/or mismatched class conflicts. It reports not
only when a class is loaded, but also where the class was loaded from,
including the path to the JAR file, assuming it came from a JAR.
jni is of little use except when working with JNI and native
libraries. When turned on, it will report various JNI events, such as when
native libraries are loaded and methods are bound; again, the output can
vary from one release or JVM to another.
5. Command-line -X
I've listed some of my favorite command-line options that the JVM provides,
but there are so many more that you could discover on your own. Running
the command-line argument
-X lists all the non-standard (but
mostly safe) arguments that the JVM provides — things like:
-Xint, which runs the JVM in interpreted mode (which can be useful for testing whether the JIT compiler is actually having an effect on your code or verifying if you have a bug in the JIT compiler).
-Xloggc:, which does the same thing as
-verbose:gcbut logs to a file instead of spewing to the command-line window.
JVM command-line options change from time to time, so periodically having a look is a good idea. It could even mean the difference between a late night spent glowering at your monitor, or going home at 5 p.m. to a lovely dinner with the spouse and kids (or slaughtering your enemies in Mass Effect 2, depending on your preference).
verbose:gc output to file is requested using the
-Xverbosegclog option on the IBM JVMs, which also allows the
specification of rolling log file generation.
Command-line flags aren't intended for permanent use in a production environment — in fact, aside from the flags that you (might) end up using to tune the JVM garbage collector, no non-standard command-line flags are really intended for production use. But as tools to peer into the inner workings of the otherwise completely opaque virtual machine, they are invaluable.
- Develop and deploy your next app on the IBM Bluemix cloud platform.
- "Java theory and practice: Garbage collection and performance" (Brian Goetz, developerWorks, January 2004): Tips for writing garbage collection-friendly classes and avoiding common performance traps.
- "G1: Java's Garbage First Garbage Collector" (Eric J. Bruno, Dr. Dobb's, August 2009): Learn about the new GC 1 algorithm, which will eventually replace the Java platform's traditional CMS mechanism.
- "My favorite HotSpot JVM flags" (Charles Nutter, Headius, January 2009): More JVM flags from a confirmed runtime fiddler.