{ by david linsin }

November 02, 2009

Having Fun with JDK's tools.jar

This week I had to trace a bug in a legacy application, I'm maintaining at the moment, which drove me up the wall. The application uses a class from JDK's tools.jar, to determine the JVM instances currently running. Unfortunately, there are incompatibilities between JDK versions.

Tracking down the bug took a humongous amount of time, because the fun part of working on a legacy application is that all the developers, which are responsible for the code you are maintaining, are usually no longer available. Don't even get me started on documentation! However, as a good developer, I created the following JUnit test, to isolate the problem from the rest of the code.

If you run this test with Sun's JRE 1.6 and tools.jar of Sun's JDK 1.6 on the classpath, you won't encounter an problems. However, with my current project, we need backward compatibility with other Java versions. That means, there are multiple tools.jar on the classpath, in different versions. Depending on their order, the test above fails or succeeds.

More precisely, there is a JDK 1.4 and 1.5 version of tools.jar on the classpath, in addition to the 1.6 version. 1.6 is needed, because in previous JDKs the class VirtualMachine doesn't reside in the package com.sun.tools.attach. So running the test without tools.jar in version 1.6, you'll get a NoClassDefFoundError.

So what's the problem you might ask? As long as tools.jar of JDK 1.6 is on the classpath, when running the aforementioned test, everything should be okay, right? It should be, but it isn't. As soon as tools.jar of JDK 1.5 is before the 1.6 version on the runtime classpath, the test fails. Every other combination works just fine.

Why tools.jar of JDK 1.5 causes this problem is a mystery to me. Sun's bug parade, doesn't contain any relevant information - at least I couldn't find any. Frankly, I think this problem is so absurd, that I cannot motivate myself getting to the bottom of it.

Nevertheless, the problem exists in our application and we'll have to find a solution. I guess that's the reason why it's a legacy application - I have to deal with problems that are totally outdated and nobody knows the answer to.


JAVAMAN said...
This comment has been removed by a blog administrator.
Dan Howard said...

Yeah the pain of using com.sun packages. I know the feeling.

insideo said...

Some cardinal rules of java development:

1) Avoid using non-public APIs.

2) Don't have multiple versions of libraries in your classpath.

3) Especially don't have multiple versions of tools.jar in your classpath (they are *very* VM-specific, and are likely to break badly when run against non-matching JVMs).

If you absolutely must use Sun's private API methods, you should create an interface for the functionality you need, and build an implementation matching each tools.jar you use. Create a factory class which uses reflection to try to instantiate the Java 6 version, the Java 5 version, etc. until you get one to load successfully. This at least insulates the rest of your app from the horror that is tools.jar.

david said...

Thanks for the advice insideo!


  • mail(dlinsin@gmail.com)
  • jabber(dlinsin@gmail.com)
  • skype(dlinsin)