The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


Mustang Beta and the JMX API

Posted by emcmanus on February 15, 2006 at 8:52 AM PST

As you'll no doubt have read elsewhere, the Mustang Beta Release is now available. There are plenty of improvements in plenty of areas, including the JMX API.

The improvements to the JMX API are incremental changes to existing functionality, rather than entirely new features. The new features will arrive in Dolphin (Java SE 7), as defined by JSR 255. (The members of the JSR 255 Expert Group were also closely involved in the JMX API changes made in Mustang.)

We don't expect there to be any significant changes to the JMX API beyond the Beta. If you felt that the weekly Mustang snapshots from mustang.dev.java.net might be too risky or too volatile, but you're tempted by the new features, now you can download the Beta and play with them. We think the Beta is pretty solid, but let us know through bugs.sun.com if you find a problem. In particular, if you find a regression (code that used to work on Tiger but doesn't work on Mustang), then you might be eligible for the Mustang regression challenge.

What's changed?

The two biggest changes to the JMX API in Mustang concern MXBeans and Descriptors.

I wrote about MXBeans recently. MXBeans provide a way to package related information together in an MBean without requiring any special configuration for clients that interact with that MBean. This is an incremental change, because MXBeans already existed in J2SE 5.0, in the package java.lang.management. What's new is that users can now define their own MXBeans, in addition to the standard set defined in java.lang.management.

I also wrote about Descriptors a while back. Descriptors give you a convenient way to attach arbitrary extra metadata to your MBeans. This is an incremental change because Descriptors have always existed in the JMX API, but only in conjunction with Model MBeans. In Mustang, Descriptors are available with all types of MBeans. This helps to erase the somewhat arbitrary distinctions between different sorts of MBeans, notably Open MBeans and Model MBeans.

Here are a few of the other improvements that Mustang brings to the JMX API.

Generification

For obscure compatibility reasons, we weren't able to generify the JMX API in Tiger. This has been fixed in Mustang. So MBeanServer.queryNames now returns a Set<ObjectName> rather than a plain Set. ObjectName.geyKeyPropertyList() returns a Hashtable<String,String> rather than a plain Hashtable (compatibility forbids us from changing it to Map<String,String>, alas). And, especially, the methods in the RelationServiceMBean are much more understandable with their new generic return types. It was pretty tough understanding what was in the Map returned by RelationServiceMBean.findAssociatedMBeans. Now that it's a Map<ObjectName,List<String>> you have a fighting chance of making sense of it.

One nice effect of generification is that you no longer need a cast in the following assignment:

SomeMBean proxy = (SomeMBean)
    MBeanServerInvocationHandler.newProxyInstance(
    	mbeanServer, objectName, SomeMBean.class, false);

As a side-note, this can now be replaced by the much easier-to-remember:

SomeMBean proxy =
    JMX.newMBeanProxy(mbeanServer, objectName, SomeMBean.class);

More powerful wildcards in ObjectName

The ObjectName class has always had support for wildcards, to define ObjectName patterns. But you could not use a wildcard within the value of a key. For example, you could not write domain:type=Dir,path="/foo/bar/*" to match an ObjectName such as domain:type=Dir,path="/foo/bar/baz" but not domain:type=Dir,path="/fred/jim/sheila". Now you can.

ObjectName implements Comparable<ObjectName>

ObjectName is now Comparable. The ordering function is a little arbitrary, but the important point here is that you can take a collection of ObjectNames, such as the result of MBeanServer.queryNames, and put them in a SortedSet to see them in a more meaningful order. For example, if I write this...

MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
Set<ObjectName> names = mbs.queryNames(null, null);
System.out.println(names.toString().replace(", ",
    	    	    	System.getProperty("line.separator")));

...then I'll get this rather random output:

[java.lang:type=MemoryManager,name=CodeCacheManager
java.lang:type=Compilation
java.lang:type=GarbageCollector,name=Copy
com.sun.management:type=HotSpotDiagnostic
java.lang:type=MemoryPool,name=Eden Space
java.lang:type=Runtime
java.lang:type=ClassLoading
java.lang:type=MemoryPool,name=Survivor Space
java.lang:type=Threading
java.lang:type=GarbageCollector,name=MarkSweepCompact
java.util.logging:type=Logging
java.lang:type=Memory
java.lang:type=OperatingSystem
java.lang:type=MemoryPool,name=Code Cache
java.lang:type=MemoryPool,name=Tenured Gen
java.lang:type=MemoryPool,name=Perm Gen
JMImplementation:type=MBeanServerDelegate]

On the other hand, if I add the following line after the assignment to names...

names = new TreeSet(names);  // a TreeSet is a SortedSet

...then I get this reasonable ordering:

[JMImplementation:type=MBeanServerDelegate
com.sun.management:type=HotSpotDiagnostic
java.lang:type=ClassLoading
java.lang:type=Compilation
java.lang:type=GarbageCollector,name=Copy
java.lang:type=GarbageCollector,name=MarkSweepCompact
java.lang:type=Memory
java.lang:type=MemoryManager,name=CodeCacheManager
java.lang:type=MemoryPool,name=Code Cache
java.lang:type=MemoryPool,name=Eden Space
java.lang:type=MemoryPool,name=Perm Gen
java.lang:type=MemoryPool,name=Survivor Space
java.lang:type=MemoryPool,name=Tenured Gen
java.lang:type=OperatingSystem
java.lang:type=Runtime
java.lang:type=Threading
java.util.logging:type=Logging]

Notifications

NotificationBroadcasterSupport constructor with MBeanInfo[]

If you have an MBean that emits notifications, it must implement the NotificationBroadcaster interface. The JMX API provides a default implementation called NotificationBroadcasterSupport. But you are supposed to override the getNotificationInfo method to return an array of all the notification types you might send. Since this array is almost always a constant, NotificationBroadcasterSupport now has a constructor that allows you to supply the array and avoid having to override getNotificationInfo().

New StandardEmitterMBean class

Speaking of MBeans that emit notifications, if you're writing a Standard MBean but you can't subclass NotificationBroadcasterSupport because you have already need to inherit from a different parent class, you can use the new StandardEmitterMBean class to build a notification-emitting MBean from your Standard MBean class. You can also use this class if you need to customize the behaviour of a notification-emitting Standard MBean, for example to change the contents of its MBeanInfo.

New Query.isInstanceOf

You can now query for MBeans that are an instance of a particular class or interface. For example, to find all Monitor MBeans in the domesne domain, you could write:

QueryExp isMonitor =
    Query.isInstanceOf("javax.management.monitor.MonitorMBean");
Set<ObjectName> monitorNames =
    mbeanServer.queryNames(new ObjectName("domesne:*"), isMonitor);

Actually, I should warn you that this will change after the Beta, and the first line will become this instead:

QueryExp isMonitor =
    Query.isInstanceOf(Query.value("javax.management.monitor.MonitorMBean"));

Alert readers will deduce that either I was lying when I said there would be no significant API changes after the Beta, or I don't consider this a significant change. Either way, this is likely to be about as significant as it will get.

Monitor Service supports complex types

Previously, the Monitor Service defined by javax.management.monitor could only monitor attributes of simple numeric types like int or double, or strings. (A reminder that this service allows you to sample an attribute periodically and send a notification if it goes over or under a certain threshold.) Now, you can monitor a value inside a complex type using a syntax like connectionStats.open.current.

The ability to pick out values like this is confined to the Monitor Service. You cannot call mbeanServer.getAttribute("connectionStats.open.current") to obtain a similar effect. (We thought about allowing that, but it could pose problems for existing code that uses attribute.names.with.dots and it's also not obvious what the corresponding behaviour for setAttribute should be.)

Address of a JMXConnector

If you have an RMI connector client obtained with code something like this...

JMXServiceURL jurl =
    new JMXServiceURL("service:jmx:rmi://blah);
JMXConnector jc = JMXConnectorFactory.connect(jurl);

...then you can now retrieve the address from jc like this...

JMXServiceURL jurl2 = ((JMXAddressable) jc).getAddress();

Here, jurl2 will be equal to jurl.

So there it is

As usual, if you have comments on these new features or the way they are specified, feel free to drop me a line at jmx-spec-comments@sun.com.

Related Topics >> Open JDK      
Comments
Comments are listed in date ascending order (oldest first)