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 2
Platform, Standard Edition 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.

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.

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.

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.

Using Sun Microsystems' 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 Sun
Microsystems' platform extensions. The following sections provide
examples of how to access a platform-specific attribute from Sun
Microsystems' implementation of the
OperatingSystemMXBean.

Monitoring Thread Contention and CPU Time

The Sun 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 Sun 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 UNIX 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.

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.

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