Java Mission Control
Since Java 7u40, the JDK has included the Java Flight Recorder tool. If you remember the available commands in jcmd, you had some JFR.* options, which are directly related to this tool. It allows you to capture a set of JVM events. It is coupled with Java Mission Control (JMC), which enables you to analyze and exploit the JVM events.
Launching it is easy:
$ $JAVA_HOME/bin/jmc
Once it is launched, you'll get a welcome screen; the view looks similar to the jvisualvm view, with a list of the available processes on the left-hand side:
You can use the same kind of hints as for jvisualvm to identify the process. If you are not quite sure, don't hesitate to use the jps -v command, which will show you the command line and its PID for each running JVM (which will allow you to identify the number in parentheses in JMC).
Once you've identified your process, you can right-click on it and select the Start JMX console to have a view similar to jvisualvm and specific to the selected JVM:
You find the CPU (processor here), the memory, and thread information, and also the MBean view, which is how the JVM can export the internal data in a standard manner.
One interesting thing is when you go to the Diagnostic Commands tab you will recognize the jcmd commands listed:
This pane allows you to execute the jcmd commands directly from the UI. Here, we are interested in the Java Flight Recorder (JFR) commands, as we want more information about our JVM.
In the previous screenshot, you may have noted that there is a Flight Recorder item on the left tree. It provides a UI for these commands. However, if you hit Start Recording, you will get the following error:
To use Java Flight Recorder, you need to add the following options to your JVM:
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder
These two options will activate the Java Flight Recorder features. To add them to GlassFish, you can edit the $GLASSFISH_HOME/glassfish/domains/domain1/config/domain.xml file and add it to the java-config block after jvm-options. Alternatively, you can use the create-jvm-options command line's glassfish command. In any case, you will need to restart (or start) your server after this modification.
If you want to test it using our maven GlassFish, you can just add them to MAVEN_OPTS:
$ MAVEN_OPTS="-XX:+UnlockCommercialFeatures -XX:+FlightRecorder" mvn embedded-glassfish:run
Now the options are activated on the JVM; you can go back to Java Mission Control and hit Start Recording on the Start Flight Recorder item. It will ask you a file location to store the recording and either a duration or a limit (size/age) for the recording. Finally, you can select whether you want to profile your server or just to monitor it. Here again, the difference is in the associated overhead. Let's select profiling for now. You can then hit Next and select what you want to monitor. An important parameter is the heap one, but if you continue through the wizard, you will see that you can precisely customize what you monitor, including the I/O. Once everything is well configured, simply hit Finish. It will proceed with the recording and open it once done.
After the recording is done, you should get a view similar to the following one, showing the captured data:
Looking at the top, we can see the event timeline. You can click on it to refine the time-slot selection. The counters show the summary of the capture in terms of memory and CPU. Finally, at the bottom, you have the CPU and memory graph.
What makes this tool more advanced than the previous one is the fact that you can visualize the code hotspot in the Code tab (the tabs are on the left in this tool) and the I/O in a single tool. The in-built JDK also makes it quite easy to use, whereas the overhead is not as important (if you select continuous monitoring, a counterpart is that the statistics won't be very accurate but close enough so as to give you an idea). A major strength of this tool is the Call Tree view of the Code tab. It allows you to associate, through a stack, the method execution time cost with the method calls. For instance, while the server was running, this capture shows that the cost of our findAll method is mainly related to the way we are mapping each quote that requires using the JPA layer (eclipselink) and the database:
This view is a really great way to investigate the hotspots of the application. It kind of merges the thread dumps and the profiling views (sometimes called Path Tracking) and enables you to get directly to the costly operations.