Documentation Contents
  previousPrevious Contents Nextnext
Chapter 4

Using the Platform MBean Server and Platform MXBeans

This chapter introduces the MBean server and the MXBeans that are provided as part of the Java Platform, Standard Edition (Java SE platform), which can be used for monitoring and management purposes. Java Management Extensions (JMX) technology MBeans and MBean servers were introduced briefly in Chapter 1, Overview of Java SE Monitoring and Management. More information about the JMX technology can be found in the JMX Technology documentation for the Java SE platform.

Using the Platform MBean Server

An MBean server is a repository of MBeans that provides management applications access to MBeans. Applications do not access MBeans directly, but instead access them through the MBean server via their unique ObjectName. An MBean server implements the interface javax.management.MBeanServer

The platform MBean server was introduced in the Java SE 5.0, and is an MBean server that is built into the Java Virtual Machine (Java VM). The platform MBean server can be shared by all managed components that are running in the Java VM. You access the platform MBean server using the java.lang.management.ManagementFactory method getPlatformMBeanServer. Of course, you can also create your own MBean server using the javax.management.MBeanServerFactory class. However, there is generally no need for more than one MBean server, so using the platform MBean server is recommended.

Accessing Platform MXBeans

A platform MXBean, is an MBean for monitoring and managing the Java VM. Each MXBean encapsulates a part of the VM functionality. A full list of the MXBeans that are provided with the platform is provided in Table 1-1 in Chapter 1, Overview of Java SE Monitoring and Management.

A management application can access platform MXBeans in three different ways.

  • Direct access, via the ManagementFactory class.

  • Direct access, via an MXBean proxy.

  • Indirect access, via the MBeanServerConnection class.

These three ways of accessing the platform MXBeans are described in the next three sections.

Accessing Platform MXBeans via the ManagementFactory Class

An application can make direct calls to the methods of a platform MXBean that is running in the same Java VM as itself. To make direct calls, you can use the static methods of the ManagementFactory class. ManagementFactory has accessor methods for each of the different platform MXBeans, such as, getClassLoadingMXBean(), getGarbageCollectorMXBeans(), getRuntimeMXBean(), and so on. In cases where there are more than one platform MXBean, the method returns a list of the platform MXBeans found.

For example, Example 4-1 uses the static method of ManagementFactory to get the platform MXBean RuntimeMXBean, and then gets the vendor name from the platform MXBean.

Example 4-1 Accessing a Platform MXBean via the ManagementFactory Class
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
String vendor = mxbean.getVmVendor(); 

Accessing Platform MXBeans via an MXBean Proxy

An application can also call platform MXBean methods via an MXBean proxy. To do so, you must construct an MXBean proxy instance that forwards the method calls to a given MBean server by calling the static method ManagementFactory.newPlatformMXBeanProxy(). An application typically constructs a proxy to obtain remote access to a platform MXBean of another Java VM.

For example, Example 4-2 performs exactly the same operation as Example 4-1, but this time uses an MXBean proxy.

Example 4-2 Accessing a Platform MXBean via an MXBean Proxy
MBeanServerConnection mbs;
...
// Get a MBean proxy for RuntimeMXBean interface
RuntimeMXBean proxy =
    ManagementFactory.newPlatformMXBeanProxy(mbs,
                                             ManagementFactory.RUNTIME_MXBEAN_NAME,
                                             RuntimeMXBean.class);
// Get standard attribute "VmVendor"
String vendor = proxy.getVmVendor();

Accessing Platform MXBeans via the MBeanServerConnection Class

An application can indirectly call platform MXBean methods through an MBeanServerConnection that connects to the platform MBean server of another running Java VM. You use the MBeanServerConnection class's getAttribute() method to get an attribute of a platform MXBean, providing the MBean's ObjectName and the attribute name as parameters.

For example, Example 4-3 performs the same job as Example 4-1 and Example 4-2, but uses an indirect call through MBeanServerConnection.

Example 4-3 Accessing a Platform MXBean via the MBeanServerConnection Class
MBeanServerConnection mbs;
...
try {
  ObjectName oname = new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
  // Get standard attribute "VmVendor"
  String vendor = (String) mbs.getAttribute(oname, "VmVendor");
} catch (....) {
  // Catch the exceptions thrown by ObjectName constructor
  // and MBeanServer.getAttribute method
  ...
}

Using Oracle JDK's Platform Extension

Java VMs can extend the management interface by defining interfaces for platform-specific measurements and management operations. The static factory methods in the ManagementFactory class will return the MBeans with the platform extension.

The com.sun.management package contains Oracle JDK's platform extensions. The following sections provide examples of how to access a platform-specific attribute from Oracle JDK's implementation of the OperatingSystemMXBean.

Accessing MXBean Attributes Directly

Example 4-4 illustrates direct access to one of Oracle JDK's MXBean interfaces.

Example 4-4 Accessing an MXBean Attribute Directly
com.sun.management.OperatingSystemMXBean mxbean =
  (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

// Get the number of processors
int numProcessors = mxbean.getAvailableProcessors();

// Get the Oracle JDK-specific attribute Process CPU time
long cpuTime = mxbean.getProcessCpuTime();

Accessing MXBean Attributes via MBeanServerConnection

Example 4-5 illustrates access to one of Oracle JDK's MXBean interfaces via the MBeanServerConnection class.

Example 4-5 Accessing an MXBean Attribute via MBeanServerConnection
MBeanServerConnection mbs;

// Connect to a running Java VM (or itself) and get MBeanServerConnection
// that has the MXBeans registered in it
...

try {
    // Assuming the OperatingSystem MXBean has been registered in mbs
    ObjectName oname = new ObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);

    // Get standard attribute "Name"
    String vendor = (String) mbs.getAttribute(oname, "Name");

    // Check if this MXBean contains Oracle JDK's extension
    if (mbs.isInstanceOf(oname, "com.sun.management.OperatingSystemMXBean")) {
        // Get platform-specific attribute "ProcessCpuTime"
        long cpuTime = (Long) mbs.getAttribute(oname, "ProcessCpuTime");
    }
} catch (....) {
    // Catch the exceptions thrown by ObjectName constructor
    // and MBeanServer methods
    ...
}

Monitoring Thread Contention and CPU Time

The ThreadMXBean platform MXBean provides support for monitoring thread contention and thread Central Processing Unit (CPU) time.

The Oracle JDK's HotSpot VM supports thread contention monitoring. You use the ThreadMXBean.isThreadContentionMonitoringSupported() method to determine if a Java VM supports thread contention monitoring. Thread contention monitoring is disabled by default. Use the setThreadContentionMonitoringEnabled() method to enable it.

The Oracle JDK's HotSpot VM supports the measurement of thread CPU time on most platforms. The CPU time provided by this interface has nanosecond precision but not necessarily nanosecond accuracy.

You use the isThreadCpuTimeSupported() method to determine if a Java VM supports the measurement of the CPU time for any thread. You use isCurrentThreadCpuTimeSupported() to determine if a Java VM supports the measurement of the CPU time for the current thread. A Java VM that supports CPU time measurement for any thread will also support that for the current thread.

A Java VM can disable thread CPU time measurement. You use the isThreadCpuTimeEnabled() method to determine if thread CPU time measurement is enabled . You use the setThreadCpuTimeEnabled() method to enable or disable the measurement of thread CPU time.

Managing the Operating System

The OperatingSystem platform MXBean allows you to access certain operating system resource information, such as the following.

  • Process CPU time.

  • Amount of total and free physical memory.

  • Amount of committed virtual memory (that is, the amount of virtual memory guaranteed to be available to the running process).

  • Amount of total and free swap space.

  • Number of open file descriptors (only for Solaris, Linux, or Mac OS X platforms).

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

Logging Management

The Java SE platform provides a special MXBean for logging purposes, the LoggingMXBean interface.

The LoggingMXBean enables you to perform the following tasks.

  • Get the name of the log level associated with the specified logger.

  • Get the list of currently registered loggers.

  • Get the name of the parent for the specified logger.

  • Set the specified logger to the specified new level.

The unique ObjectName of the LoggingMXBean is java.util.logging:type=Logging. This object name is stored in LogManager.LOGGING_MXBEAN_NAME.

There is a single global instance of the LoggingMXBean, which you can get by calling LogManager.getLoggingMXBean().

The Logging MXBean defines a LoggerNames attribute describing the list of logger names. To find the list of loggers in your application, you can select the Logging MXBean under the java.util.logging domain in the MBeans tab, and double-click on the value field of the LoggerNames attribute. The Logging MXBean also supports two operations.

  • getLoggerLevel: Returns the log level of a given logger.

  • setLoggerLevel: Sets the log level of a given logger to a new level.

These 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.

Detecting Low Memory

Memory use is an important attribute of the memory system. It can be indicative of the following problems.

  • Excessive memory consumption by an application.

  • An excessive workload imposed on the automatic memory management system.

  • Potential memory leakages.

There are two kinds of memory thresholds you can use to detect low memory conditions: a usage threshold and a collection usage threshold. You can detect low memory conditions using either of these thresholds with polling or threshold notification. All these concepts are described in the next sections.

Memory Thresholds

A memory pool can have two kinds of memory thresholds: a usage threshold and a collection usage threshold. Either one of these thresholds may not be supported by a particular memory pool. The values for the usage threshold and collection usage threshold can both be set using the MBeans tab in JConsole.

Usage Threshold

The usage threshold is a manageable attribute of some memory pools. It enables you to monitor memory use with a low overhead. Setting the threshold to a positive value enables a memory pool to perform usage threshold checking. Setting the usage threshold to zero disables usage threshold checking. The default value is supplied by the Java VM.

A Java VM performs usage threshold checking on a memory pool at the most appropriate time, typically during garbage collection. Each memory pool increments a usage threshold count whenever the usage crosses the threshold.

You use the isUsageThresholdSupported() method to determine whether a memory pool supports a usage threshold, since a usage threshold is not appropriate for some memory pools. For example, in a generational garbage collector (such as the one in the HotSpot VM; see Garbage Collection in Chapter 3, Using JConsole), most of the objects are allocated in the young generation, from the Eden memory pool. The Eden pool is designed to be filled up. Garbage collecting the Eden memory pool will free most of its memory space since it is expected to contain mostly short-lived objects that are unreachable at garbage collection time. So, it is not appropriate for the Eden memory pool to support a usage threshold.

Collection Usage Threshold

The collection usage threshold is a manageable attribute of some garbage-collected memory pools. After a Java VM has performed garbage collection on a memory pool, some memory in the pool will still be in use. The collection usage threshold allows you to set a value for this memory. You use the isCollectionUsageThresholdSupported() method of MemoryPoolMXBean to determine if the pool supports a collection usage threshold.

A Java VM may check the collection usage threshold on a memory pool when it performs garbage collection. Set the collection usage threshold to a positive value to enable checking. Set the collection usage threshold to zero (the default) to disable checking.

The usage threshold and collection usage threshold can be set in the MBeans tab of JConsole.

Memory MXBean

The various memory thresholds can be managed via the platform MemoryMXBean. The MemoryMXBean defines the following 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 Garbage Collection (GC) verbose tracing setting. This can be set dynamically. The GC verbose traces will be displayed at the location specified when you start the Java VM. The default location for GC verbose output of the Hotspot VM is stdout.

The Memory MXBean supports one operation, gc, for explicit garbage collection requests.

Details of the Memory MXBean interface are defined in the java.lang.management.MemoryMXBean specification.

Memory Pool MXBean

The MemoryPoolMXBean platform MXBean defines a set of operations to manage memory thresholds.

  • getUsageThreshold()

  • setUsageThreshold(long threshold)

  • isUsageThresholdExceeded()

  • isUsageThresholdSupported()

  • getCollectionUsageThreshold()

  • setCollectionUsageThreshold(long threshold)

  • isCollectionUsageThresholdSupported()

  • 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. For more information, see the API reference documentation for the MemoryPoolMXBean class.

Polling

An application can continuously monitor its memory usage by calling either the getUsage() method for all memory pools or the isUsageThresholdExceeded() method for memory pools that support a usage threshold.

Example 4-6 has a thread dedicated to task distribution and processing. At every interval, it determines whether it should receive and process new tasks based on its memory usage. If the memory usage exceeds its usage threshold, it redistributes outstanding tasks to other VMs and stops receiving new tasks until the memory usage returns below the threshold.

Example 4-6 Using Polling
pool.setUsageThreshold(myThreshold);
....
boolean lowMemory = false;
while (true) {
  if (pool.isUsageThresholdExceeded()) {
    lowMemory = true;
    redistributeTasks();  // redistribute tasks to other VMs
    stopReceivingTasks();  // stop receiving new tasks
  } else {
    if (lowMemory) { // resume receiving tasks
      lowMemory = false;
      resumeReceivingTasks();
    }
    // processing outstanding task
    ...
  }
  // sleep for sometime
  try {
    Thread.sleep(sometime);
  } catch (InterruptedException e) {
    ...
  }
}      

Example 4-6 does not differentiate the case in which the memory usage has temporarily dropped below the usage threshold from the case in which the memory usage remains above the threshold between two iterations. You can use the usage threshold count returned by getUsageThresholdCount() to determine if the memory usage has returned below the threshold between two polls.

To test the collection usage threshold instead, you use the isCollectionUsageThresholdSupported(), isCollectionThresholdExceeded() and getCollectionUsageThreshold() methods in the same way as above.

Threshold Notifications

When the MemoryMXBean detects that a memory pool has reached or exceeded its usage threshold, it emits a usage threshold exceeded notification. The MemoryMXBean will not issue another usage threshold exceeded notification until the usage has fallen below the threshold and then exceeded it again. Similarly, when the memory usage after garbage collection exceeds the collection usage threshold, the MemoryMXBean emits a collection usage threshold exceeded notification.

Example 4-7 implements the same logic as Example 4-6, but uses usage threshold notification to detect low memory conditions. Upon receiving a notification, the listener notifies another thread to perform actions such as redistributing outstanding tasks, refusing to accept new tasks, or allowing new tasks to be accepted again.

In general, you should design the handleNotification method to do a minimal amount of work, to avoid causing delay in delivering subsequent notifications. You should perform time-consuming actions in a separate thread. Since multiple threads can concurrently invoke the notification listener, the listener should synchronize the tasks it performs properly.

Example 4-7 Using Threshold Notifications
class MyListener implements javax.management.NotificationListener {
  public void handleNotification(Notification notification, Object handback)  {
    String notifType = notification.getType();
    if (notifType.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED)) {
      // potential low memory, redistribute tasks to other VMs & stop receiving new tasks.
      lowMemory = true;
      notifyAnotherThread(lowMemory);
    }
  }
}

// Register MyListener with MemoryMXBean
MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
NotificationEmitter emitter = (NotificationEmitter) mbean;
MyListener listener = new MyListener();
emitter.addNotificationListener(listener, null, null);

Assuming this memory pool supports a usage threshold, you can set the threshold to some value (representing a number of bytes), above which the application will not accept new tasks.

pool.setUsageThreshold(myThreshold);

After this point, usage threshold detection is enabled and MyListener will handle notification.

previousPrevious Contents Nextnext

Oracle and/or its affiliates Copyright © 1993, 2022, Oracle and/or its affiliates. All rights reserved.
Contact Us