Using JConsole to Monitor Applications

By Mandy Chung
Published December 2004

The Java 2 Platform, Standard Edition (J2SE) 5.0 release provides comprehensive monitoring and management support. It not only defines the management interfaces for the Java virtual machine, but also provides out-of-the-box remote monitoring and management on the Java platform and of applications that run on it. In addition, JDK 5.0 includes the Java Monitoring and Management Console (JConsole) tool. It uses the extensive instrumentation of the Java virtual machine to provide information on performance and resource consumption of applications running on the Java platform using Java Management Extension (JMX) technology.

The article describes how JConsole can be used to observe information about an application running on the Java platform. The article first gives an overview of the J2SE 5.0 monitoring and management architecture and how JConsole plugs into the architecture. It then describes how to use JConsole to access several core monitoring and management functionalities provided by the Java platform including:

  • Detect low memory
  • Enable or disable GC and class loading verbose tracing
  • Detect deadlocks
  • Control the log level of any loggers in an application
  • Access OS resources
  • Manage an application's Managed Beans (MBeans)

Architectural Overview

Figure 1 shows the architecture of J2SE 5.0 monitoring and management support. In the 5.0 release, the Java virtual machine (JVM) is highly instrumented for monitoring and management. The platform instrumentation provides information on performance, resource consumption, and the JVM and logging settings of applications running on the Java platform.

JMX provides a standard way to instrument the Java runtime environment and applications, and the JMX Remote API allows that instrumentation to be accessed remotely. The instrumentation is accessible through the JMX managed bean (MBean) interfaces, which are registered in the platform MBean server. Applications can also create their own MBeans and register them in the platform MBean server, which can serve as a single point for remote access. A JMX-compliant client, such as JConsole, can connect to the platform MBean server and manage the application (as well as the Java platform) using JMX technology.

Figure 1: Architecture of J2SE 5.0 Monitoring and Management Support
Figure 1: Architecture of J2SE 5.0 Monitoring and Management Support.

Platform Beans

The Java platform provides a set of platform MBeans (Managed Beans) for monitoring and management of the Java virtual machine and the logging facility:

Platform MBean Description Class loading system of the Java virtual machine. Compilation system of the Java virtual machine. Memory system of the Java virtual machine. Memory manager in the Java virtual machine. Memory pool in the Java virtual machine. Garbage collector in the Java virtual machine. Threading system of the Java virtual machine. Runtime system of the Java virtual machine. Operating system on which the Java virtual machine is running.
java.util.logging.LoggingMXBean Logging facility.

An MBean is a managed object that follows the design patterns conforming to the JMX specification. An MBean can represent a device, an application, or any resource that needs to be managed. The management interface of an MBean comprises a set of readable and/or writable attributes and a set of invokable operations. MBeans can also emit notifications when predefined events occur.

Each platform MBean has a rich set of attributes and operations such as memory usage, thread CPU usage, garbage collection statistics, and so on. Some might also emit notifications. We will explore a few platform MBeans in the following sections.

The JConsole Tool

JConsole is a JMX-compliant GUI tool that connects to a running JVM, which started with the management agent. To start an application with the management agent for local monitoring, set the system property when you start the application. For example, to enable the J2SE sample application Java2Demo for local monitoring, enter the following command:

   JDK_HOME/bin/java -jar JDK_HOME /demo/jfc/Java2D/Java2Demo.jar

where JDK_HOME is the directory containing the JDK 5.0. The Monitoring and Management Using JMX document provides detailed information on out-of-the-box remote management.

To start JConsole, run

   JDK_HOME /bin/jconsole

A connection dialog box opens, whose Local tab lists any JVMs running on the local system started with the same user ID as JConsole, along with their process ID and class/argument information.

Figure 2: Local Tab
Figure 2: Local Tab.

Jconsole can connect to a running JVM in 3 different ways:

  • Local. Connects to a Java virtual machine running on the local system using JConsole that is executed with the same user name. JConsole connects to the platform MBean server using an RMI connector with authentication that uses the filesystem access permission. This local monitoring connection capability is only available in Sun's JDK.
  • Remote. Connects to a JMX agent using an RMI connector with the following URL:
    service:jmx:rmi:///jndi/rmi://hostName:portNum/jmxrmi where hostName is the host name and portNum is the port number specified when the JMX agent was enabled. JConsole will pass the user name and password as client credentials as authentication to the RMI connector server by setting the "jmx.remote.credentials" property to these values in the environment map for establishing the connection.
  • Advanced. Connects to a JMX agent with the specified URL. You typically use this to connect to a JMX agent using a custom connector other than RMI connector, or an application running on JDK 1.4 with the Reference Implementation of JMX (JSR-3) and JMX Remote (JSR-160).

When JConsole successfully establishes the connection, it obtains information from the JVM MBeans in the connected JMX agent, and displays the information in the following tabs:

  • Summary tab. Summary information on the JVM and on monitored values.
  • Memory tab. Information on memory use.
  • Threads tab. Information on thread use.
  • Classes tab. Information on class loading
  • VM tab. Information on the JVM
  • MBeans tab. Information on all MBeans

The MBeans tab displays information on all MBeans registered in the target JVM in a generic way. The MBeans tab allows you to access the full set of the platform instrumentation, including those that are not visible in the other tabs. Note that the other tabs present some of the information on the platform MBeans. In addition, you can monitor and manage your application's MBeans using this MBeans tab.

Using MBeans Tab to Monitor and Manage MBeans

All platform and application MBeans that are registered in the connected JMX agent can be accessed through the MBeans tab. For example, the Memory MBean is defined as follows:

   public interface MemoryMXBean {
       public MemoryUsage getHeapMemoryUsage();
       public MemoryUsage getNonHeapMemoryUsage();
       public int         getObjectPendingFinalizationCount();
       public boolean     isVerbose();
       public void        setVerbose(boolean value);
       public void        gc();

The Memory MBean contains four attributes:

  • HeapMemoryUsage. A read-only attribute describing the current heap memory usage.
  • NonHeapMemoryUsage. A read-only attribute describing non-heap memory usage.
  • ObjectPendingFinalizationCount. A read-only attribute describing the number of objects pending for finalization.
  • Verbose. A boolean attribute describing the GC verbose tracing setting. This can be set dynamically.

The Memory MBean supports one operation, gc, for explicit garbage collection requests. Details of the MBean interface are defined in the specification. You can use the MBeans tab to access all these attributes and operations.

Figure 3: MBeans Tab
Figure 3: MBeans Tab.

The tree on the left shows the list of all MBeans, organized by their object names. An MBean object name consists of a domain name and a list of key properties. For example, the platform MBeans for the JVM are all grouped under the "java.lang" domain, where the logging MBean is under the "java.util.logging" domain. The format of an MBean object name is described in the specification.

When you select an MBean in the tree, its attributes, operations, notifications, and other information are displayed on the right. You can set the value of attributes, if they are writeable (the value is displayed in blue). You can invoke operations displayed in the Operations tab. You can also watch for the notifications emitted by an MBean: by default, JConsole does not listen to any notification emitted by an MBean until you subscribe to it. You can click the "Subscribe" button to subscribe to notifications or the "Unsubscribe" button to unsubscribe.

Figure 4: MBeans Notification
Figure 4: MBeans Notification.

Detecting Low Memory


The Memory tab provides information about memory consumption, memory pools, and garbage collection statistics by accessing the memory system, memory pools, garbage collector MBeans.

Figure 5: Memory Tab
Figure 5: Memory Tab.

The chart shows the memory usage over time, for heap and non-heap memory, and for specific memory pools. The memory pools available depend on the JVM being used. The following list shows the pools for the HotSpot virtual machine.

  • Eden Space (heap) Pool from which memory is initially allocated for most objects.
  • Survivor Space (heap) Pool containing objects that have survived GC of eden space.
  • Tenured Generation (heap) pool containing objects that have existed for some time in the survivor space.
  • Permanent Generation (non-heap). Holds all the reflective data of the virtual machine itself, such as class and method objects. With JVMs that use class data sharing, this generation is divided into read-only and read-write areas.
  • Code Cache (non-heap) The HotSpot JVM also includes a "code cache" that contains memory used for compilation and storage of native code.

The Details area shows several current memory metrics:

  • Used The amount of memory currently used. Memory used includes the memory occupied by all objects including both reachable and unreachable objects.
  • Committed The amount of memory guaranteed to be available for use by the JVM. The amount of committed memory may change over time. The Java virtual machine may release memory to the system and committed could be less than the amount of memory initially allocated at startup. Committed will always be greater than or equal to used.
  • Max The maximum amount of memory that can be used for memory management. Its value may change or be undefined. A memory allocation may fail if the JVM attempts to increase the used memory to be greater than committed memory, even if the amount used is less than or equal to max (for example, when the system is low on virtual memory).
  • Usage Threshold The usage threshold of a memory pool. This field will only be shown if the memory pool supports usage threshold.
  • GC time The cumulative time spent on garbage collection and the total number of invocations. It may have multiple rows, each of which represents one garbage collector algorithm used in the JVM.

The bar chart on the lower right shows memory consumed by the memory pools in the JVM. The bar turns red when the memory used exceeds the usage threshold. The usage threshold is one of the attributes defined in the Memory Pool MBean for low memory detection support. A set of methods defined in the MemoryPoolMXBean interface for low memory detection support follows.

   public interface MemoryPoolMXBean {

       // Usage threshold 
       public long    getUsageThreshold();
       public void    setUsageThreshold(long threshold);
       public boolean isUsageThresholdExceeded();
       public boolean isUsageThresholdSupported();

            // Collection usage threshold
       public long    getCollectionUsageThreshold();
       public void    setCollectionUsageThreshold(long threshold);
       public boolean isCollectionUsageThresholdSupported();
       public boolean isCollectionUsageThresholdExceeded();

Each memory pool may have two kinds of memory thresholds for low memory detection support: a usage threshold and a collection usage threshold. Either one of these thresholds might not be supported by a particular memory pool.

Usage Threshold

The usage threshold is a manageable attribute of a memory pools. It enables the monitoring of memory use with low overhead. Setting the threshold to a positive value enables usage threshold checking for a memory pool. Setting the usage threshold to zero disables usage threshold checking. The default value is supplied by the JVM. A JVM performs usage threshold checking on a memory pool at the most appropriate time, typically during GC and sometimes at allocation time. If the JVM detects that the current memory usage exceeds the usage threshold, it will set the UsageThresholdExceeded attribute to true.

Some memory pools may not support the usage threshold. You can use the UsageThresholdSupported attribute to determine whether a memory pool supports a usage threshold. For example, in a generational garbage collector (such as the HotSpot virtual machine), most of the objects are allocated in the young generation, from the "eden" memory pool. The eden pool is designed to be filled up; performing garbage collection on the eden memory pool will free most of its memory space since it is expected to contain mostly short-lived objects unreachable at garbage collection time. So, having the eden memory pool to support the usage threshold is not only not useful but also might not be implemented efficiently.

Collection Usage Threshold

Collection usage threshold is a manageable attribute of some garbage-collected memory pools. After a JVM has performed garbage collection on a memory pool, some memory in the pool will still be occupied by reachable objects. The collection usage threshold allows you to set a value to check against the memory usage only after garbage collection. If the JVM detects that the memory usage exceeds the collection usage threshold, it will set the CollectionUsageThresholdExceeded attribute to true.

You can use the CollectionUsageThresholdSupported attribute to determine if the pool supports a collection usage threshold.

The usage threshold and collection usage threshold is set in the MBeans tab. For example, select the TenuredGen memory pool in the left tree, set the usage threshold of the tenured generation memory pool to 6 Mbytes.

Figure 6: Setting Usage Threshold
Figure 6: Setting Usage Threshold.

When the memory usage of the TenuredGen memory pool exceeds 6 MBytes, part of the bar representing the TenuredGen memory pool will turn red to indicate the portion of used memory that exceeds the usage threshold. The bar representing the heap memory will also turn red. You can either click on the bar or select a specific memory pool in the Chart menu to switch to the information about a specific memory pool. If you hover the cursor over a bar, the name of the memory pool it represents will be displayed.

Figure 7: Low Memory
Figure 7: Low Memory.

Enabling or Disabling VM Verbose Tracing

As described earlier, the memory system MBean defines a boolean attribute called Verbose that allows you to turn the GC verbose tracing on or off dynamically. The GC verbose traces will be displayed at the location specified at JVM startup. The default location for GC verbose output of the Hotspot virtual machine is stdout.

To enable or disable the GC verbose tracing, select the Memory MBean and set the Verbose attribute to true or false. Similarly, the class loading MBean also has the Verbose attribute, which can be set to enable or disable class loading verbose tracing.

Figure 8: Setting Verbose GC
Figure 8: Setting Verbose GC.

Detecting Deadlocks

The Threads tab provides information about threads running in an application.

Figure 9: Threads Tab
Figure 9: Threads Tab.

The Threads list in the lower left lists all the active threads. If you enter a string in the Filter field, the Threads list will show only those threads whose name contains the string you enter. You can get the thread dump of a thread by clicking on the name of a thread in the Threads list.

The Threading MBean provides several other useful operations that are not covered by the Threads tab:

  • findMonitorDeadlockedThreads. Detects if any threads are deadlocked on the object monitor locks. This operation returns an array of deadlocked thread IDs.
  • getThreadInfo. Returns the thread information. This includes the name, stack trace, and the monitor lock that the thread is currently blocked on, if any, and which thread is holding that lock, and thread contention statistics.
  • getThreadCpuTime. Returns the CPU time consumed by a given thread

To access these additional features, go to the MBeans tab and select the Threading MBean in the MBeans tree. It lists all the attributes and operations for accessing information in the JVM being monitored.

Figure 10: MBeans Tab Threading
Figure 10: MBeans Tab Threading.

To check if your application has run into a deadlock (for example, your application seems to be hanging), you can invoke the findMonitorDeadlockedThreads operation.

Figure 11: Find Deadlocked Threads
Figure 11: Find Deadlocked Threads.

Once you click on the findMonitorDeadlockedThreads button, the Operation Return Value window pops up to show the result. In the example above, JConsole connects to the sample application SampleTest, which has three threads in deadlock. It detects that threads of ID 12, 10, and 11 are deadlocked, as shown in the preceding figure. To find out more information about the deadlocked threads, you can use the getThreadInfo operation. The Threading MBean supports the getThreadInfo operation in four different forms, which obtain thread information:

  • Of a given thread ID with stack trace of the specified maximum number of frames.
  • Of an array of thread IDs with stack trace of the specified maximum number of frames.
  • Of a given thread ID with no stack trace.
  • Of an array of thread IDs with no stack trace.

For a deadlock situation, you would typically be interested in the stack trace. You can enter the thread ID of a deadlocked thread in the first parameter of the getThreadInfo operation (say, ID = 12) and the number of frames you want to get as the second parameter (depth = 5).

Figure 12: ThreadInfo for Thread ID = 1
Figure 12: ThreadInfo for Thread ID = 12.

Double-clicking on the value field of the stackTrace attribute will show a Composite Navigation view that allows you to traverse the stack trace. Figures 13 and 14 show the Composite Navigation view that displays the top and second top frame of the stack trace of DeadlockedThread-1.

Figure 13: Top Frame of the Stack Trace of DeadlockedThread
Figure 13: Top Frame of the Stack Trace of DeadlockedThread-1.

Figure 14: Second Frame of the Stack Trace of DeadlockedThread
Figure 14: Second Frame of the Stack Trace of DeadlockedThread-1.

The Threads tab provides a more user-friendly way to look at the stack trace of a thread. You can find the name of the deadlocked threads using the getThreadInfo operation. Then you can use the Threads tab to analyze the deadlock:

  • DeadlockedThread-1 is blocked to enter a monitor lock owned by DeadlockedThread-2
  • DeadlockedThread-2 is blocked to enter another monitor lock owned by DeadlockedThread-3
  • DeadlockedThread-3 is blocked to enter another monitor lock owned by DeadlockedThread-1

Controlling Log Level

The Logging MBean defines a LoggerNames attribute describing the list of logger names. To find the list of loggers in your application, select the Logging MBean under the java.util.logging domain in the MBeans tree and then double-click on the value field of the LoggerNames attribute.

Figure 15: List of All Logger Names
Figure 15: List of All Logger Names.

The Logging MBean also supports three operations:

  • getParentLoggerName. Returns the name of the parent logger of a given logger.
  • getLoggerLevel. Returns the log level of a given logger.
  • setLoggerLevel. Sets the log level of a given logger to a new level.

All three operations take a logger name as the first parameter. To change the level of a logger, enter the logger name in the first parameter and the name of the level it should be set to in the second parameter of the setLoggerLevel operation, and then enter the setLoggerLevel button. The SampleTest application has its own logger com.sun.example.hello, which is included in the preceding list of logger names. You can invoke the setLoggerLevel operation to set the com.sun.example.hello logger to FINEST level. A pop-up window appears, showing whether the method is successfully invoked or there is an error.

Figure 16: Setting Log Level
Figure 16: Setting Log Level.

Accessing OS Resources—Sun's Platform Extension

The JDK 5.0 extends the Operating System MBean to include certain OS resource information such as:

  • the process CPU time
  • the amount of total and free physical memory
  • the amount of committed virtual memory (that is, the amount of virtual memory guaranteed to be available to the running process)
  • the amount of total and free swap space
  • the number of open file descriptions (UNIX only)

When the Operating System MBean in the MBeans tab is selected, you see all the attributes and operations including the platform extension. You can monitor the changes of a numerical attribute over time—for example, the process CPU time—by double-clicking the value field of the attribute.

Figure 17: MBeans Tab OS
Figure 17: MBeans Tab OS.

In addition, the VM tab and the Summary tab provide information on the operating system resources.

Managing Application MBeans

The SampleTest application being monitored has its own Hello MBean with the object name:


If the CacheSize attribute is changed, the Hello MBean will send a notification. You can use the MBeans tab to manage your application's MBeans, as well as the platform MBeans. For example, you might want to monitor when the CacheSize attribute is changed. You first subscribe to the notifications in the Notification tab. If you change the CacheSize to 300, you will see one notification sent out.

Figure 18: Notifications
Figure 18: Notifications.


The JConsole tool demonstrates the comprehensiveness and ease-of use of the JDK 5.0's monitoring and management features. You can use JConsole to connect to a running Java virtual machine, and then monitor the memory usage and thread activity. You can obtain class-loading information, plus information on the JVM and the operating system. JConsole also gives you a generic way to access MBeans, such that you can access the full set of instrumentation of the Java platform and also manage your application.

We described how to access several core monitoring and management functionalities provided by the Java platform through JConsole, including low memory detection, virtual machine verbose tracing, deadlock detection, and logger level control.

Related Information

About the Author

Mandy Chung is a Senior Staff Engineer in the Java Serviceability Group at Sun Microsystems. She designed and implemented the JVM monitoring and management interface in JDK 5.0 and led the JConsole development. She holds a masters degree in Computer Science from the University of California, Davis, and a B.S. in Computer Studies from the University of Hong Kong.