There are plenty of well-known profiler options in the market such as YourKit, JProfiler and Java Mission Control, however I’m going with VisualVM for this walkthrough.
Having been available in the JDK bin directory since JDK 1.6, VisualVM offers an effective (and tried-and-tested) way to monitor both local and remote Java applications running on a JVM via an easy-to-use visual interface.
Embedded in the JDK, it’s not only useful for displaying application configuration and runtime environment, but perfect for identifying memory consumption issues. What’s more, when it comes to thread dumps it can be very useful in detecting deadlock and race conditions and heap dumps can assist in analyzing the heap allocation.
- helps track memory leaks
- analyzes the heap data
- ensures that memory usage is optimized
- monitors the GC
- profiles the CPU
In order to demonstrate the effectiveness of VisualVM, I’ll be monitoring an Apache Tomcat instance on which the Spring 4 application described on one of my previous blog posts is deployed.
To run VVM, simply navigate through a shell to your JDK software's bin directory and type jvisualvm, (or double-click on the icon if you’re working on Windows).
In the image below, you’ll notice the Applications window, whose nodes can be expanded to view running applications and saved files. For most nodes, you can view additional information, and also perform actions, by right-clicking a node and choosing an item from the popup menu.
The Local node view displays the name and PID of Java applications that are running on the same system as VisualVM. When you expand the Local node, it automatically displays the currently running Java applications (note that it is itself always listed as one of the local applications). When a new local Java application is launched, a new node appears under the Local node view and it disappears when the application terminates. The same applies to the Remote node view.
If you use VisualVM to take thread dumps, heap dumps or profiling snapshots of an application, they are displayed as sub-nodes below the node for that application. You can right-click a dump or snapshot sub-node to save it to your local system. You can archive all the information collected about an application and save it as an application snapshot.
The image to the right helps illustrate that, if we expand the Local node, it will show our running Apache Tomcat instance.
If we double-click on it, a window with a few tabs opens on the right (see below)
Along the top of that new window are a series of tabs. The first of these is the Overview tab, which displays basic infromation. Note that JMX remote is not enabled - we don’t need it because the server is local. However, you might need to enable it if your application and your VisualVM don’t run on the same machine.
The Monitor tab shows real-time, high-level data on the memory heap, thread activity, and the classes loaded in the JVM. This monitoring data is displayed in the following graphs:
Heap: the Heap graph displays the total heap size and how much of the heap is currently used. These are the figures that a Java application can obtain using the java.lang.Runtime.totalMemory() and java.lang.Runtime.freeMemory() calls.
Classes: this graph displays an overview of the total number of loaded classes and shared classes.
Threads: the Threads graphs displays an overview of the number of live and daemon threads in the application's JVM. You can use VisualVM to take a thread dump if you want to capture and view exact data on application threads at a specific point in time.
The Monitoring tab also contains buttons that enable you to perform garbage collection immediately, as well as taking a Heap Dump. When you take a heap dump, a tab displaying the heap dump opens in the application tab and a node appears as a timestamped node in the Applications window.
The Classes view within the Heap dump (see below) displays a list of classes and the number and percentage of instances referenced by that class. You can view a list of the instances of a specific class by right-clicking the name and choosing Show in Instances View.
In the next tab,Threads, VisualVM displays real-time, high-level data on thread activity. You can click a thread in the timeline to view more about that thread in the Details tab.
Within Threads, the Timeline tab displays a timeline with real-time thread states. The drop-down list enables you to select which threads are displayed; you can choose to view all threads, live threads or finished threads. You can also select a single thread or multiple threads to display a subset of the threads. A timeline for each thread provides a quick overview of the thread's activity.
Another useful feature of VisualVM is the possibility to take a thread dump (stack trace) while a local application is running. Taking a thread dump does not stop the application, you just get a printout of the thread stack that includes thread states for the Java threads: that could be very convenient in cases where a command-line console for the application is not available. You can use a stack trace to help diagnose a number of issues, such as deadlocks, or to get more information when an application hangs.
See image below for the example:
Hopefully this quick-start guide has helped you understand a bit more about how to utilise one of the most versatile and powerful tools available within the JDK.
VisualVM has a great community behind it, and users are welcome to extend the existing code - for example, if you have a monitoring or management tool that you want to make available to VisualVM, you could create a plugin that adds new tabs and menu items, allowing VisualVM users to benefit from the feature set provided by your tool. More information about this can be found here.