Cryptic error messages in Java
We are dealing with complex stuff in Plumbr. Hacking JVM internals, bytecode manipulation, data mining – we are all over it. But some of us also teach young developers who are doing their first steps in the Java wilderness. And year after year we see those youngsters run into the same problems over and over again. At least part of those problems seem to be related with the cryptic ways Java has chosen to explain developers about the problem at hand.
JRE vs JDK
Unable to locate tools.jar. Expected to find it in C:\Java\jre\lib\tools.jar
This is the infamous message which stuns novices effectively for hours. For all the experienced guys it is crystal clear that the young developer has installed JRE instead of JDK. Or at least his PATH is pointing to JRE instead of the JDK. Or something else along those lines. But why does the message need to be that confusing? What about “Your JVM runs on JRE. But you need to install JDK for the operations it needs to perform. Download it from URL”.
Out of Memory messages
java.lang.OutOfMemoryError: Java heap space
That one is actually our bread and butter. Being a clear call to action for hardware administrators that it is time to toss more physical RAM towards the machine they are responsible for. Really, I have seen this happen on several occasions. But even when equipped with a bit more insight about JVM internals – why can’t this message include a bit more information? Like your current heap size and what can you do to increase it? Believe me, each year there is a bazillon new Java developers and system administrators why are struggling to figure out what the heck has happened in this situation.
java.lang.UnsupportedClassVersionError: Unsupported major.minor eu.plumbr.demo.version.Main version (49.0)
Thats a nice way to say to a developer that the code is compiled using a newer JDK than the one which is used to run it. Why was it so difficult to change the message to something a human can easily grasp? Like “You are running on a JDK 6.0, the application you are trying to run is compiled with a newer JDK (> 6.0) Either upgrade your JDK or recompile the application with an older version”. But apparently it was easier just to grab the minor and major versions from the version of class file format and be done with it.
Exception in thread "main" java.lang.IllegalAccessException: Class eu.plumbr.demo.accessor.Accessor can not access a member of class eu.plumbr.demo.accessordiff.Accessible with modifiers "public"
These beasts tend to take different forms, but one recent encounter revealed itself in the shape visible in the above. All I was trying to do was to invoke a public method via reflection. Which should be accessible from anywhere, just as the truly helpful message is telling. Which is about as helpful as telling to a man in burning house that he should try to put out fires. The underlying problem was in accessing a member of a nonpublic type from another package. Which was definitely a mistake. But again – mr Error Message, why can’t you enclose the actual reason?
Exception in thread "main" java.lang.ClassCastException: eu.plumbr.demo.classcast.Invoice cannot be cast to eu.plumbr.demo.classcast.Invoice
Apparently this Invoice is not good enough to be an Invoice. When loaded in a different classloader. This makes all the sense in the world if you are familiar with the JVM spec and know that class is identified by its package, name and classloader it was loaded from. But this is something you can’t even google a solution for. And why on earth cannot the error message indicate the conflicting classloaders and why I have to dig into the hell of bootstrap / application server / ear / war / custom classloaders to figure it out? This error wants to unleash my internal troll about classloading and resource management in general, but lets just stick with one sample here.
All-in-all, none of the cryptic messages above is probably not going to be a showstopper on its own. But out there has to be hundreds of waitresses and whatnot who just gave up at some point when studying programming. There is a chance that if those messages were designed with human aspects in mind some of them might have stuck around and finally made it through – to the land where no error message is too complex to understand an no problem too tough to debug. So if any of our readers is a language designer then maybe you will think not only to Java masters, but to all the young Padawans out there as well …