Dustin's Pages

Saturday, April 30, 2016

Programmatic jcmd Access

Questions posed online demonstrate the occasional desire of developers to access via their Java applications the types of information normally gained from running JConsole, VisualVM, or JDK command-line tools externally against the application. Here are some examples of those types of questions:

The Tools Enhancements in JDK 8 page states, "JDK 8 provides remote access to diagnostic commands which were previously accessible only locally via the jcmd tool. Remote access is provided using the Java Management Extensions (JMX), so diagnostic commands are exposed to a platform MBean registered to the platform MBean server. The MBean is the com.sun.management.DiagnosticCommandMBean interface." In the post Looking at DiagnosticCommandMBean in JConsole and VisualVM, I looked at using JMX and DiagnosticCommandMBean via JConsole and VisualVM to access jcmd type information on a running JVM process.

The DiagnosticCommandMBean is accessed via JMX using the ObjectName "com.sun.management:type=DiagnosticCommand". Most of the operations require no arguments and return a String. With this in mind, a general approach to accessing these operations that have String[] signatures, a String return type, and don't actually require a parameter is shown in the following code snippet.

Setting Up DiagnosticCommandMBean and General Method for Accessing Operations of Same Signature

With the code above in place, the method invokeNoStringArgumentsCommand(String, String) can be used to access several of the operations that DiagnosticCommandMBean provides. The help sub-command is useful when used with jcmd because it lists the available sub-commands associated with a specified Java process. Likewise, the "help" operation provided by the DiagnosticCommandMBean is similarly helpful in providing a list of commands that the MBean supports. This is easy to access with the code shown next that uses the code just shown.

In my blog post Determining the Active HotSpot Garbage Collector, I wrote that jcmd can be used to identify the VM flags of a running Java process and that, from those flags, one can glean which garbage collector is in use. Because the DiagnosticCommandMBean supports the VM.flags operation as shown above, this operation can be used to view the VM flags and, from those flags, determine which collector is in use. The next code listing shows two example methods with the first accessing the VM flags of the process and the second method providing a simplistic example of how to use the first method to identify the garbage collector in use.

The examples already shown (accessing help and VM flags) are demonstrative of the same general approach that can be used to programmatically access other operations on DiagnosticCommandMBean with the same signature. A series of code listings and corresponding output are shown next to illustrate some of these.

Some of the sub-commands available with jcmd are only available when diagnostic operations are unlocked with -XX:+UnlockDiagnosticVMOptions (specified when running the Java process). This is true of the DiagnosticCommandMBean counterparts as demonstrated in the next code listing and output listing.

One jcmd subcommand I have not seen exposed as an operation on DiagnosticCommandMBean is that for generating a heap dump (jcmd's GC.heap_dump). There is no equivalent operation exposed by DiagnosticCommandMBean as far as I can tell from looking at the exposed operations in VisualVM and JConsole and from looking at the available commands listed by the "help" operation as demonstrated above. Although DiagnosticCommandMBean does not appear to provide an operation for invoking a heap dump, another MBean (com.sun.management.HotSpotDiagnostic with ObjectName of "com.sun.management:type=HotSpotDiagnostic") does with operation "dumpHeap" and this is demonstrated in A. Sundararajan's's blog post "Programmatically dumping heap from Java applications."

Conclusion

The DiagnosticCommandMBean provides most of jcmd's functionality and it therefore makes jcmd functionality available to Java applications to run that functionality against themselves.

The code listings shown in this post are available in the class VirtualMachineDiagnostics, which is available on GitHub. I may add or modify this class in the future, but the original version has the same code as shown in this post.