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 with their unique ObjectName
. An MBean server
implements the interface javax.management.MBeanServer
.
J2SE 5.0 introduces the platform MBean server, an MBean
server built-in to the JVM, which can be shared by all managed
components running in the JVM. You access the platform MBean server
with the method
ManagementFactory.getPlatformMBeanServer()
.
Of course, you can also create your own MBean server using the
MBeanServerFactory
class. However, there is
generally no need for more than one MBean server, so using the platform MBean server is recommended.
Platform MBeans (MXBeans) were introduced previously. A management application can access platform MBeans three different ways:
An application can directly call the methods of a platform
MBean running in the same Java virtual machine. To do so, use
the static methods of the ManagementFactory
class. ManagementFactory
has accessor
methods for each platform MBean such as
getClassLoadingMXBean()
,
getGarbageCollectorMXBeans()
,
getRuntimeMXBean()
, and so on. In the cases
where there are more than one platform MBean, the method returns a
List
of platform MBeans.
For example, the following code uses the static method of
ManagementFactory
to get the platform MBean
RuntimeMXBean
, and then gets the vendor name from the
platform MBean:
RuntimeMXBean mxbean = ManagementFactory.getRuntimeMXBean();
String vendor = mxbean.getVmVendor();
An application can also call platform MBean methods through an
MXBean proxy. To do so, construct an MXBean proxy instance that
forwards the method calls to a given MBeanServer by calling the
static method
ManagementFactory.newPlatformMXBeanProxy()
. An
application typically constructs a proxy to remotely access a
platform MBean of another JVM.
For example, the following code does the same thing as the previous example, but using 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();
An application can indirectly call platform MBean methods
through an MBeanServerConnection
connecting to the
platform MBeanServer of a running JVM. You use the
getAttribute()
method of
MBeanServerConnection
to get an attribute of a
platform MBean, providing the MBean's ObjectName
and
the attribute name as parameters.
For example, the following code does the same thing as the
previous two examples, but uses an indirect call through
MBeanServerConnection
:
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
...
}
JVM implementations may extend the management interface by
defining interfaces for platform-specific metrics 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 examples show how to access a platform-specific
attribute from Sun's implementation of the
RuntimeMXBean.
This example illustrates direct access to the Sun-specific MXBean interface:
com.sun.management.OperatingSystemMXBean mxbean =
(com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
// Get the number of processors
int numProcessors = mxbean.getAvailableProcessors();
// Get the Sun-specific attribute Process CPU time
long cpuTime = mxbean.getProcessCpuTime();
This example illustrates access to the Sun-specific MXBean interface via MBeanServerConnection:
MBeanServerConnection mbs;
// Connect to a running JVM (or itself) and get MBeanServerConnection
// that has the JVM 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 "OperatingSystem"
String vendor = (String) mbs.getAttribute(oname, "OperatingSystem");
// Check if this MXBean contains Sun's extension
if (mbs.isInstanceOf(oname, "com.sun.management.RuntimeMXBean")) {
// Get platform-specific attribute "ProcessCpuTime"
BarType bar = (String) mbs.getAttribute(oname, "ProcessCpuTime");
}
} catch (....) {
// Catch the exceptions thrown by ObjectName constructor
// and MBeanServer methods
...
}
The ThreadMXBean
platform MBean provides support for monitoring thread contention and thread CPU time.
The Sun HotSpot JVM supports thread
contention monitoring. Use the
ThreadMXBean.isThreadContentionMonitoringSupported()
method to determine if a JVM supports thread contention monitoring.
Thread contention monitoring is disabled by default. Use the
setThreadContentionMonitoringEnabled()
method to
enable it.
The Sun HotSpot JVM supports measuring
thread CPU time on most platforms. The CPU time provided by this interface has nanosecond precision
but not necessarily nanosecond accuracy.
Use the isThreadCpuTimeSupported()
to determine
if a JVM supports measuring of the CPU time for any
thread and isCurrentThreadCpuTimeSupported()
to determine if a JVM supports measuring of
the CPU time for the current thread.
A Java virtual machine implementation that supports CPU time measurement
for any thread will also support that for the current thread.
A JVM may disable thread CPU time measurement.
Use the isThreadCpuTimeEnabled()
method to determine if thread CPU time measurement is enabled
. Use the setThreadCpuTimeEnabled()
method to enable/disable this thread CPU time measurement.
Memory use is an important attribute of the memory system. It can indicate:
As described below, 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.
Note: Memory monitoring is intended for load-balancing or workload distribution: for example, an application could stop receiving new workload when its memory usage exceeds a certain threshold. Memory monitoring is not intended to enable an application to detect and recover from a low memory condition.
For more information, see the API reference for MemoryPoolMXBean.
A memory pool may 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 usage threshold is a manageable attribute of some memory pools. It enables monitoring 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. Each memory pool increments a usage threshold count whenever the usage crosses the threshold.
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 HotSpot
VM), 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
unreachable at garbage collection time. So, it is not appropriate
for the eden memory pool to support a 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 in use. The collection usage threshold allows you to set a
value for this memory. Use the isCollectionUsageThresholdSupported()
method
of MemoryPoolMXBean to determine if the pool supports a collection
usage threshold.
A JVM may check the collection usage threshold on a memory pool when it performs GC. Set the collection usage threshold to a positive value to enable checking. Set the collection usage threshold to zero (the default) to disable checking.
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.
The following example has a thread dedicated to task distribution and processing. At every interval, it determines if 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.
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) {
...
}
}
The above example does not differentiate the case where the
memory usage has temporarily dropped below the usage threshold from
the case where 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 collection usage threshold instead, you would use the isCollectionUsageThresholdSupported()
, isCollectionThresholdExceeded()
and getCollectionUsageThreshold()
methods similarly.
When the 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.
The example code below implements the same logic as in the polling example, but uses usage threshold notification to detect low memory conditions. Upon receiving notification, the listener notifies another thread to perform actions such as to redistribute outstanding tasks, stop receiving tasks, or resume receiving tasks.
In general, design the handleNotification method to do a minimal amount of work, to avoid causing delay in delivering subsequent notifications. Perform time-consuming actions in a separate thread. Since multiple threads can concurrently invoke the notification listener, the listener should properly synchronize the tasks it performs.
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 then set the threshold to some value (representing a number of bytes), above which the app will not accept new tasks.
pool.setUsageThreshold(myThreshold);
After this point, usage threshold detection is enabled and
MyListener will handle notification.