Mustang Beta and the JMX API
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.
- Login or register to post comments
- Printer-friendly version
- emcmanus's blog
- 1449 reads





