Java debugging and the class loader
Have you ever been working on some java code, when all of the sudden it appears that the app is NOT doing what you expect? Perhaps the app is not even behaving in a manner that follows your current code but rather is executing as though it was several versions behind?
A java exception from another dimension?
I recently ran into an issue like this where I was trying to debug an exception… Of course, the exception stack trace provided the class and code line where the exception occurred. The weird part was that this line was completely different than my current code. Just by looking at the code and the exception stack trace I knew for a fact that the current code that I had saved and was compiling did not contain the functionality that the exception was complaining about…
Obviously, the java classpath was picking up an old version… but from where? I usually do my development and debugging in Eclipse and that was no help. The nefarious exception was occurring in both eclipse and the command line!
Fortunately, someone I know recently had to figure out a similar problem and showed me a cool solution that shows you the exact file system path that the class was loaded from.
ProtectionDomain to the rescue
Classes can be loaded from jar file(s), the file system, remote URL’s or generated on the fly. As a project becomes more complex, understanding the class loading model becomes increasingly difficult. ProtectionDomain is a little known class that can be easily accessed via the Class.getProtectionDomain() method. This class provides the infrastructure needed to determine the absolute path to where a compiled class was loaded from.
For example, you may have multiple components, each with separate library folders that contain any number and any combination of jars and folders that contain various classes. Even worse, you may have different versions of the same classes in different locations all of which may be on the classpath! Ugh… without an automated method for indicating where a class was loaded from, debugging bizarre issues like an old version in the classpath can be a nightmare.
Determining the class location within Eclipse
When using the Eclipse debugger, all you have to do is place a break point at the first line in the main method. Then open the Expressions view and add a new expression which will execute on the breakpoint. The key to making this work in Eclipse is to use the static class as opposed to a runtime class instance. This is because the Expression code executes outside the scope of a live object instance.
Let’s assume that you have a class called net.henryranch.LocationTest and you want to find out where it was loading from… In the Expressions view, simply add this new Expression:
The benefit of this approach is that you don’t have to modify your class source code in order for it to work. Just set a breakpoint, add the expression and execute the app in a debug configuration.
Determining the class location within a running app
This approach requires that you modify the source code of your class, but does not require Eclipse or a debugger.
Again, assuming that you have a class called net.henryranch.LocationTest simply add the following line wherever you want in the class.
While this approach is pretty simple, it can provide the developer with a powerful tool when debugging in complex environments. Hopefully you never work in an environment where the classpath can be polluted with more than one version of a build artifact, but just in case you do, now you know how to figure out where that other worldly implementation is lurking…