JVisualVM – the UI for JVM monitoring
The jcmd command is a great command-line tool but is a bit raw. However, the JVM provides additional tooling to yield metrics linked to performance and, in particular, the CPU and memory. JVisualVM and JConsole are two such tools packaged with the JDK (not the JRE). Since both are pretty similar, we will only deal with JVisualVM in this section, but most of the information and tools can be used with JConsole as well.
To launch JVisualVM, you just have to execute a command of the same name:
$ $JAVA_HOME/bin/jvisualvm
Once launched, you will see the welcome screen of jvisualvm:
To start using jvisualvm, you will need to select a JVM. This is done through the tree on the left-hand side of the screen. The two options are Local and Remote. In this case, we'll run the server on our local machine, so it is automatically detected by jvisualvm (just ensure to start it from the same JDK as the one the server is using). In the previous screenshot, you can see three processes:
- VisualVM: This is a Java process and detects itself.
- GlassFish: This is a standalone GlassFish server.
- org.codehaus.plexus.classworlds.launcher.Launcher: This is a maven process. If you start GlassFish with maven, as we saw in Chapter 1, Money – The Quote Manager Application, this is the process to choose.
Once you have identified your process in the list, you need to double-click on it and you will get the following screen showing high-level information about the process:
Once you have selected a JVM on the left, the right pane will show information about the JVM. It is organized in tabs:
- Overview: This gives high-level information about the JVM (process ID, main class, arguments, Java version, system properties, and so on).
- Monitor: This gives an overview of the CPU usage, the memory usage (in particular, the heap), the number of classes loaded, and the number of threads.
- Threads: This gives a live view of the existing threads managed by the JVM and shows the thread state over time (whether it is idled or active). Here is a screenshot:
The legend is in the bottom-right corner and uses colors to help this view to be readable: green for running, purple for sleeping, yellow for wait, red for fork, and orange for monitor.
What is interesting are the green blocks. This is when a thread does something. If you take the http-listener(x) threads for instance, you can see that they are orange and green. The orange part is when the threads are waiting for requests and the green part is when they are serving something. This view must be coupled with the thread dumps (or thread stack view) to ensure that the waiting threads are actually waiting for something relevant (such as waiting for some I/O), which the application does not control.
- Sampler: This tab is very interesting and allows you to capture what the server is doing in terms of CPU and memory. We find some information that we had with jcmd, but this is easier to use. All you need to do is to click on the CPU or Memory button and jvisualvm will start capturing the related information. Here is the memory view that you will get once some samples have been captured:
This view is really close to the GC histogram command of jcmd; you'll find the class name, the corresponding size in bytes, and the number of instances. You can filter the visible classes at the bottom using any pattern related to your application; in this screenshot, we filtered by Quote.
If you capture some CPU samples, the view is centered on the methods and their execution time:
The first column is the method identifier and the other columns show the corresponding time for the respective methods. Self Time is the time of the method itself. Self Time (CPU) is the same but ignores waiting time (locks and so on). Same goes for the Total Time columns. What is the main difference between the Self Time and the Total Time columns? The Total Time columns include further method calls, which the Self Time columns don't.
- Profiler: This is the last tab of the JVM view and provides more or less the same view as the Sampler tab. The main difference is the way it captures the data. Don't worry if the time between your click and the first data you can see is quite long in Profiler. While the Sampler tab just takes a screenshot of the JVM (memory or thread stacks) from time to time and generates approximate statistics from them, the Profiler tab modifies the classes (actual bytecode) to capture accurate data. This implies that the sampling overhead is not very huge but the profiling overhead can be if it affects all the codebase, including the fast methods (which are instrumented by default). If you want precise metrics, you will need to use the profiler, but it is recommended that you hit the Settings checkbox to precisely tune which classes you want to get the metrics for and not let the defaults, which are too wide to not affect the system.