Summer is of course the time when people take their vacation, and nowhere more so than here in France. You could be forgiven for thinking that the entire country grinds to a halt between the traditional vacation boundaries of the 14th of July (Bastille Day) and the 15th of August (Feast of the Assumption, a public holiday, don't ask). It seems like three quarters of high-street shops are closed for business. More to the point, three quarters of my co-workers are also on vacation, so, if I'm not, then the amount of time I spend in discussion and co-ordination is drastically reduced.
This summer I had a period of about two weeks like that where I could just lower my head and code. And that was a good thing, because there was something that really needed to be done.
The MBean Server is the core of the JMX API, and its implementation in the JDK includes code that dates from the very earliest release of that API, and indeed its proprietary predecessors. That means it's had six years or more to accumulate bug-fixes, interesting ideas that didn't quite work out, new features that were grafted on as best we could, and so on.
The last straw for me was the addition of MXBeans to the JMX API. MXBeans were initially implemented as a standalone package that used only the public JMX API. When the MXBean feature was added to Mustang, we just did the minimal adaptation work to make it work. It was still operating as a standalone package, taking no advantage of the implementation classes in the rest of the JMX API. The idea was to get the feature in place quickly, then revisit it later to clean up.
If you're like me, you're extremely sceptical about things that "we'll clean up later". Somehow, if it works, it never does get cleaned up. There's always something more urgent to do. I could see this coming a mile off for MXBeans.
This was bad for a number of reasons. MXBeans and Standard MBeans have a great deal in common. In fact you could consider that Standard MBeans are just MXBeans where the type mapping is the identity. So the fact that they shared almost no code meant that there was a lot of functionality implemented twice. Bug-fixes applied to one wouldn't automatically apply to the other. New features, such as annotations for descriptor contents would have to be implemented separately for each one. And optimizations in one wouldn't appear in the other.
This was exactly the situation we were in during the French shutdown. Standard MBeans had lots of caching logic so that the same MBeanInfo instance could be shared between all MBeans of the same type, and only computed for the first of them. MXBeans didn't have that, but they did cache Method objects so they didn't have to be retrieved again for every getAttribute or invoke on the MBean.
So, out with the hatchet. Refactor the logic for Standard MBeans and MXBeans so that they are just two concrete subclasses of an abstract MBean class. Put the caching of MBeanInfo objects and Methods into this class. Use the Visitor Pattern so the same introspection logic can construct MBeanInfo, method cache, and proxy data.
In this sort of environment, you have to pay lots of attention to WeakReferences so that all the cached information goes away when it's no longer used. It's really easy to set things up so that if you register an MBean from some class loader and then unregister it again, the class loader object is still referenced and can never be garbage collected.
While I had the hatchet out, I changed the way MBeans are handled so that every MBean is ultimately a DynamicMBean. Standard MBeans and MXBeans get wrapped in a DynamicMBean. The previous logic had separate handlers for Dynamic MBeans and Standard MBeans, and that tended to produce gratuitous inconsistencies between the two.
The intent of all these changes is to simplify the code, so future evolution will be easier; to reduce per-MBean memory usage; and to speed up MBean operations. The first of these is hard to measure but the measurements I've made on the other two are very encouraging. These changes will appear in build 53 of Mustang, which should be available on java.net on about the 23rd of September.