If you are a regular reader of this blog then you are probably aware that I do most of my software development using Java. A default install of Ubuntu (10.10) includes the OpenJDK based IcedTea version of Java 6. This is a version of Java that is covered by an open-source license -- which is in comparison to the Sun/Oracle version of Java for which you can read the source but which was not covered by an open-source licence (it's now "mostly" covered by GPL v2 with the classpath exception). I've never really understood the philosophical argument behind IcedTea and the need for a clean room implementation of Java, although Oracle's recent attack on Android provides some explanation. Anyway, given that it was the default installation of Java I was willing to give it a try. Within minutes though I'd found two show stopping bugs and so have switched back to using the reliable Sun/Oracle release of Java 6.
The first bug is visual and one that I knew existed in earlier versions of IcedTea but which I hoped had been fixed by now. In essence the ImageIO JPEG reader in IcedTea doesn't properly handle JPEG images with embedded colour profiles. What you end up with is an image that looks like a a photographic negative rather than the image you tried to load. This bug basically means that you can't use IcedTea for any application that allows users to load arbitrary JPEG files. For me this means I can't recommend it for running Convert4Frame, TagME, PhotoGrid or 3DAssembler. Also I can't use IcedTea to run the tomcat server in which I host my cookbook web app. What is really annoying about this bug is that it was originally in the main Sun/Oracle distribution, reported all the way back in 2003, but was fixed in Java 5 update 4, you can read all about it in the bug report. If the open-source version can't fix a bug that is around eight years old then why do they even bother!
The second bug is a little stranger but no less annoying. The documentation for the method
ClassLoader.loadClass(String name)
states that either it returns the resulting Class
object or throws a ClassNotFoundException
if (wait for it) the class was not found. That all seems perfectly logical to me. Unfortunately there appears to be at least one situation in which IcedTea returns null
instead of throwing an exception when the class cannot be found.I distribute a lot of the open-source Java software that I develop in my spare time via Web Start and once I had Ubuntu up and running I thought I'd check Java by launching 3DAssembler. Unfortunately it failed to load and gave me a rather strange
NullPointerException
. After a bit of digging around (the version of the app on my website doesn't match my development version and hence the line numbers were out) I eventually tracked the problem back to this try/catch block.try { Class rmClass = Assemble3D.class.getClassLoader().loadClass("org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager"); RepaintManager.setCurrentManager((RepaintManager)rmClass.getConstructor().newInstance()); System.err.println("EDT Debug Mode Is Active"); } catch (ClassNotFoundException e) { // the debug classes from SwingHelper are not available }This code tries to load a class, via reflection, that catches EDT violations (painting Swing components from the wrong thread) and that I only use during development to aid in debugging. I load the class via reflection so that when I distribute the application I can simply leave out the JAR file containing the debug class and everything will continue to work -- the class isn't found so an exception is thrown, caught and ignored and the application continues on. The problem with IcedTea is that when running as a Web Start application the call to
loadClass
in line 2 returns null
instead of throwing a ClassNotFoundException
. This means that the catch block isn't triggered and the exception is thrown all the way out of the main method, killing the application. It seems to only be a Web Start issue as running my development copy locally under IcedTea doesn't cause loadClass
to return null
. Of course this problem I can fix by changing the catch block to trap all exceptions, but the point is I shouldn't have to!As I said at the beginning of this post I'm all for open-source software, but I believe there are cases where developers who give their time freely to projects should think more about the merits of the project and if it is really needed. The "official" Oracle release of Java is now, for all intense and purposes, under an open-source license for the development of desktop applications (mobile and embedded uses are a different kettle of fish). Given this, is there really any need for a clean room implementation, especially when that implementation is so buggy as to render it useless in many situations?
Welcome to the world of differing Java implementations :) It turns out that "write once run anywhere" was the biggest myth that Sun ever pushed about Java. It's a subtle problem between platform specific variations of Sun's own JVM but in a-whole-nother league when independent implementations come about.
ReplyDeleteAs for your final paragraph - I can't work out which is more incendiary: trying to tell open source folks how to use their freely donated time or opening the can of worms about the relative openness of various open source licences - Good luck with that :P
Cheers,
Rob
Okay, I agree in retrospect that last paragraph was a little more incendiary than I intended. I really should have calmed down a little between figuring out what the problem was and writing the blog post! Next time I'll go find a long cool drink (I think I'll go with beer rather than iced tea) before blogging.
ReplyDeleteI have never fully understood the differences between the different open-source licences and I'm guessing those people who donate their time to develop IcedTea have a good reason for doing so. Maybe in penance for the post I'll try and write a fix for that second bug and submit a patch.