Permalink
Browse files

Create VirtualMachineDiagnostics.java

Initial version of VirtualMachineDiagnostics.java used in blog post "Programmatic jcmd Access" on "Inspired by Actual Events" blog (http://marxsoftware.blogspot.com/).
  • Loading branch information...
1 parent e70b874 commit 4b1a7724b6db2a0832f667b620f4dc4e4d3cde07 @dustinmarx committed May 1, 2016
Showing with 188 additions and 0 deletions.
  1. +188 −0 dustin/utilities/diagnostics/VirtualMachineDiagnostics.java
@@ -0,0 +1,188 @@
+package dustin.utilities.diagnostics;
+
+import static java.lang.System.out;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+import java.lang.management.ManagementFactory;
+
+/**
+ * Provide virtual machine diagnostics using DiagnosticCommandMBean
+ * that comes with the Oracle HotSpot JVM.
+ */
+public class VirtualMachineDiagnostics
+{
+ /** Object Name of DiagnosticCommandMBean. */
+ public final static String DIAGNOSTIC_COMMAND_MBEAN_OBJECT_NAME =
+ "com.sun.management:type=DiagnosticCommand";
+
+ /** My MBean Server. */
+ private final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+ /** Platform MBean Server. */
+ private final ObjectName objectName;
+
+ /**
+ * Create an instance of me with the provided object name.
+ *
+ * @param newObjectName ObjectName associated with
+ * DiagnosticCommand MBean.
+ */
+ private VirtualMachineDiagnostics(final ObjectName newObjectName)
+ {
+ this.objectName = newObjectName;
+ }
+
+ /**
+ * Only publicly available method for instantiating an instance
+ * of me.
+ *
+ * @return An instance of me.
+ */
+ public static VirtualMachineDiagnostics newInstance()
+ {
+ try
+ {
+ final ObjectName objectName = new ObjectName(DIAGNOSTIC_COMMAND_MBEAN_OBJECT_NAME);
+ return new VirtualMachineDiagnostics(objectName);
+ }
+ catch (MalformedObjectNameException badObjectNameEx)
+ {
+ throw new RuntimeException(
+ "Unable to create an ObjectName and so unable to create instance of VirtualMachineDiagnostics");
+ }
+ }
+
+ /**
+ * Provide class statistics as single String.
+ *
+ * This is only supported when {@code -XX:+UnlockDiagnosticVMOptions} is enabled.
+ *
+ * @return Single string containing formatted class statistics.
+ */
+ public String getClassStatistics()
+ {
+ return invokeNoStringArgumentsCommand("gcClassStats", "GC Class Statistics");
+ }
+
+ /**
+ * Provide class histogram as single String.
+ *
+ * @return Single string containing formatted class histogram.
+ */
+ public String getHistogram()
+ {
+ return invokeNoStringArgumentsCommand("gcClassHistogram", "GC Class Histogram");
+ }
+
+ /**
+ * Provide thread dump as single String.
+ *
+ * @return Single string containing formatted thread dump.
+ */
+ public String getThreadDump()
+ {
+ return invokeNoStringArgumentsCommand("threadPrint", "Thread Dump");
+ }
+
+ /**
+ * Provide virtual machine uptime as single String.
+ *
+ * @return Single string containing virtual machine uptime.
+ */
+ public String getVirtualMachineUptime()
+ {
+ return invokeNoStringArgumentsCommand("vmUptime", "Virtual Machine Uptime");
+ }
+
+ /**
+ * Provide list of supported operations (help).
+ *
+ * @return Single string containing names of supported operations.
+ */
+ public String getAvailableOperations()
+ {
+ return invokeNoStringArgumentsCommand("help", "Help (List Commands)");
+ }
+
+ /**
+ * Provide a String representing the Virtual Machine flags.
+ *
+ * @return String containing the virtual machine flags.
+ */
+ public String getVirtualMachineFlags()
+ {
+ return invokeNoStringArgumentsCommand("vmFlags", "Determine VM flags");
+ }
+
+ /**
+ * Provide String representing active/current garbage collector.
+ *
+ * @return String representation of current garbage collector
+ * ("Parallel/Throughput", "Concurrent Mark Sweep (CMS)",
+ * "Garbage First", or "UNDETERMINED").
+ */
+ public String determineGarbageCollector()
+ {
+ String garbageCollector;
+ final String vmFlags = getVirtualMachineFlags();
+ if (vmFlags.contains("+UseParallelGC") || vmFlags.contains("+UseParallelOldGC"))
+ {
+ garbageCollector = "Parallel/Throughput";
+ }
+ else if (vmFlags.contains("+UseConcMarkSweepGC"))
+ {
+ garbageCollector = "Concurrent Mark Sweep (CMS)";
+ }
+ else if (vmFlags.contains("+UseG1GC"))
+ {
+ garbageCollector = "Garbage First";
+ }
+ else
+ {
+ garbageCollector = "UNDETERMINED";
+ }
+ return garbageCollector;
+ }
+
+ /**
+ * Invoke operation on the DiagnosticCommandMBean that accepts
+ * String array argument but does not require any String
+ * argument and returns a String.
+ *
+ * @param operationName Name of operation on DiagnosticCommandMBean.
+ * @param operationDescription Description of operation being invoked
+ * on the DiagnosticCommandMBean.
+ * @return String returned by DiagnosticCommandMBean operation.
+ */
+ private String invokeNoStringArgumentsCommand(
+ final String operationName, final String operationDescription)
+ {
+ String result;
+ try
+ {
+ result = (String) server.invoke(objectName, operationName, new Object[] {null}, new String[]{String[].class.getName()});
+ }
+ catch (InstanceNotFoundException | ReflectionException | MBeanException exception)
+ {
+ result = "ERROR: Unable to access '" + operationDescription + "' - " + exception;
+ }
+ return result;
+ }
+
+ public static void main(final String[] arguments)
+ {
+ final VirtualMachineDiagnostics instance = VirtualMachineDiagnostics.newInstance();
+ out.println("VM Flags:\n\t" + instance.getVirtualMachineFlags());
+ out.println("Garbage Collector: " + instance.determineGarbageCollector());
+ out.println("Histogram:\n" + instance.getHistogram());
+ out.println("Thread Stack:\n" + instance.getThreadDump());
+ out.println("VM Uptime: " + instance.getVirtualMachineUptime());
+ out.println("Class Statistics: " + instance.getClassStatistics());
+ out.println("Supported Operations:\n" + instance.getAvailableOperations());
+ }
+}

0 comments on commit 4b1a772

Please sign in to comment.