I’ve recently added a few more JDKs into the compatibility tests of my ObMimic library, and have found a few issues that seem worth noting here.
1 JDKs Added
The specific JDKs added into the testing were:
This isn’t a comprehensive examination of the JDKs themselves, but just tests that:
- The ObMimic code all works correctly on all of the JDKs.
- The Ant build script delivered as part of ObMimic’s “Enterprise Edition” can successfully build ObMimic from its source code on the Java SE 7 and higher JDKs (including running its tests and generating its Javadoc).
- The deliverables produced by the “Enterprise Edition” build script do themselves work correctly on all of the JDKs.
For details of the other JDKs that were already included in the testing, further background information and previous findings, refer to the earlier post Some specific issues from ObMimic portability testing.
The only significant changes since that earlier post are that the tests are now run on 64-bit systems (with the Linux system now being Ubuntu 12.10); and the ObMimic “Enterprise Edition” build script is limited to Java SE 7 or higher (as it now needs Servlet 3.1, which in turn requires Java SE 7 or higher).
3 Issues Encountered
The issues encountered on the newly-added JDKs were as follows:
3.1 IBM Java SE 6 Logger doesn’t successfully look-up message keys
The java.util.logging.Logger methods that take a “msg” argument are supposed to accept a message key and look it up in a ResourceBundle to translate it into the actual message to be used (substituting given parameters into the message where applicable). This is supposed to follow the usual rules for finding the most relevant localization of the resource bundle.
There’s one ObMimic test case that relies on this, as it’s testing that a custom Handler correctly processes calls that use a message key. This test case works on all other JDKs, including IBM Java SE 5 and 7, but on IBM Java SE 6 it fails – the message key is written to the log “as is” rather than being converted into the full message from the resource bundle.
I’ve not found any definitive explanation or bug report for this, but there is a comment from “tripl3des” within a Can’t find bundle… post in an IBM discussion forum that says
“ResourceBundle implementation for IBM JDK does not respect the contract described in the API. At least not for 1.6 version…. IBM JDK only works when there is a file for the exact locale requested.”
If true, that sounds similar to what I’m encountering here (though there are other types of message look-ups throughout ObMimic that are working correctly).
The test case that fails isn’t critical to ObMimic (it’s just part of the full testing of an optional feature in some “common” code that’s bundled with ObMimic); there doesn’t appear to be anything wrong with the source code; and it all works OK on all the other JDKs.
At any rate, unless and until I learn any different I’m assuming this is just a bug in this particular JDK – and that anybody using this JDK’s java.util.logging facilities will encounter this in any logging with message keys, not just if they happen to do such logging whilst using the custom “handler” that I’m testing.
So whilst I don’t like having JDK-specific tests, in this particular case I’ve decided the most appropriate solution is to just skip this one specific test when running on IBM Java SE 6.
3.2 IBM Java SE 6 and 7 bootclasspath is more complex than just “rt.jar”
Until now, ObMimic’s “Enterprise Edition” build script has been explicitly specifying a “bootclasspath” that points to the /jre/lib/rt.jar of the JDK it’s using..
This has been done because the build’s default settings specify Java 5 as the “source” and “target” level, and javac issues a warning if these aren’t accompanied by an explicit “bootclasspath”. Explicitly supplying the “bootclasspath” doesn’t really achieve anything other than cutting out the warning message, as the build with default settings doesn’t know of any JDK other than the one it’s running on and can only specify that JDK’s own boot classes. But under the circumstances the warning is superfluous and distracting, and seemed worth cutting out.
Unfortunately, the IBM JDKs for Java 6 and 7 need more than just “rt.jar”. Some of the core Java classes (including, for example, java.lang.String) are in a separate “vm.jar”. To make matters worse, this is in different locations in IBM JDK 6 and IBM JDK 7. Then there are other necessary classes in other jars within the /jre/lib directory structure.
As a result, javac and javadoc on the IBM JDKs seem to work OK when it’s left to its own devices, but once an explicit bootclasspath is given they seem to need lots of jars from various locations within /jre/lib.
There are VM options for adding specific jars into the default bootclasspath instead of completely replacing it, and one could always configure the bootclasspath to include any and all jars within the entire /jre/lib directory structure. However, I’m not sure enough of an appropriate way to set the bootclasspath that will work for the IBM JDKs whilst also being entirely safe and appropriate for all other JDKs.
In the end I’ve modified the build script to not specify the bootclasspath at all. This re-introduces the warning message about it not being specified, but it works on all of the JDKs and is perhaps safer and more “truthful” than artificially suppressing the message.
In any case, the warning can always be avoided by changing the build properties that set the “source” and “target” levels if you don’t actually need compatibility with JDKs earlier than the one you’re building on.
3.3 Stricter Javadoc checking in JDK 8
Building the code on JDK 8 resulted in lots of Javadoc errors!
It turns out that by default Javadoc on JDK 8 carries out much stricter checking of the Javadoc content. This includes checking for incorrect HTML tags, characters that ought to be escaped/encoded, HTML attributes that are necessary for accessibility etc.
This appears to be a result of the “JDK Enhancement Proposal” JEP 172 DocLint.
In my case it found:
- Quite a few “&” characters and a few “<” and “>” characters that needed escaping;
- Numerous silly little mistakes in HTML tags (e.g. “<ul>” that should have been “</ul>”);
- Some tables that were missing “summary” or “caption” attributes.
I can see this coming as a bit of a shock to many people when they switch to JDK 8 and suddenly discover that their builds fail with lots of Javadoc errors!
There’s apparently an “-Xdoclint” option that can be used to turn off some or all of the checks, but of course it makes more sense to actually fix the errors. If your Javadoc is otherwise reasonable there might be a large number of these errors, but each should be pretty trivial to fix.
It took me an hour or two to fix all of these Javadoc errors in the ObMimic code, but as always it feels good to have found and fixed these and to know that this is now checked by each Javadoc run.
3.4 A JDK 8 b99 Javadoc bug?
I also hit an apparent Javadoc bug on JDK 8 build b99 where it gives an error plus a warning for “@throws X” where “X” is a type parameter of the method (it looks like some of the Javadoc processing is taking the “X” as a class name rather than recognising it as the method’s type parameter).
However, there already seem to be JDK changes in progress that might be relevant. So for now I’m assuming this is just an early-access quirk that will get fixed in due course.
I’ve implemented a temporary (rather hacky!) work-around for the single ObMimic method affected by this, but it doesn’t seem worth going into any more detail here on the assumption that this will turn out to be a purely temporary issue.