For demonstration purposes, I'll be running a simple Java application. The code for this application is not significant for demonstrating how to determine the applicable garbage collector. The simple Java application can be run with the command java -cp stringInstantiationsDemo.jar dustin.examples.demo.IndefiniteRun. Notice that there is no specification of a JVM flag for the garbage collector to be used. This means that the JVM will use an ergonomically selected garbage collector.

As the last screen snapshot indicates, use of the -XX:+PrintCommandLineFlags demonstrates the existence of the -XX:+UseParallelGC flag, which indicates that the collector being used automatically in this case is the parallel collector (also known as throughput collector).

Use of the -XX:+PrintCommandLineFlags allows us to see the ergonomically selected garbage collector works well when starting a new Java application. When we want to see the garbage collector used by an already-running Java process, jcmd comes in handy (I wrote about this useful tool in the post jcmd: One JDK Command-Line Tool to Rule Them All). This is illustrated in the next screen snapshot that demonstrates use of jcmd to see the JVM command-line flags of an already-running Java application.

From the previous image, we see that we can use jcmd <pid> VM.flags to identify virtual machine flags that will indicate the garbage collector being used. In this case, we again see the presence of -XX:+UseParallelGC, indicating use of the parallel/throughput garbage collector.

I just demonstrated using jcmd to see the implicit JVM arguments that tell us which garbage collector was automatically chosen for a particular application's VM when the garbage collector was not explicitly specified. The next two images show that JConsole and VisualVM do NOT show implicit JVM arguments and so do NOT show the garbage collector being used automatically when one is not specified.

Although neither JConsole nor VisualVM shows implicit Java Virtual Machine arguments such as the implicitly chosen garbage collector, both tools can still be used to determine the garbage collector in use via JMX and the GarbageCollectorMXBean with object type java.lang:type=GarbageCollector. In the case of the simple application used so far in this post, this will be java.lang:type=GarbageCollector,name=PS MarkSweep because this is the parallel or throughput collector. This is demonstrated in JConsole and VisualVM (via the MBeans plugin) in the next two screen snapshots.

The above examples have demonstrated three basic approaches to determining which garbage collector is applicable. These are summarized in the following table for the parallel/throughput collector previously demonstrated as well as for the other two main Oracle HotSpot JVM collectors (CMS and G1). The table shows what to look for when ascertaining which collector (parallel, CMS, or G1) is in use with one of the approaches described above (explicitly specified on command-line, jcmd, or JMX MXBean).

The JVM generally prevents two different garbage collectors' flags from being provided. When two exist on the same attempt to launch a Java application, a message like "Conflicting collector combinations in option list" will appear and the Java process won't start. Therefore, one simply needs to identify a flag for a specific collector associated with a running Java application to know which collector is in use. This post has demonstrated multiple simple approaches that can be used to identify which HotSpot garbage collector is being applied in a given application's JVM.