Documentation Contents

|  | Previous | Contents |  | Next

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.
|  | Previous | Contents |  | Next

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