The Value of Decompiling Java Code

The inspection of a stack trace is a crucial part of a developer’s methodology for determining the source of an error or bug. In some environments, the stack trace can be quite large. I was once working in a WebSphere environment and was asked to try and determine why some of the application related stack traces we were seeing did not include any application code references. Without a reference to the application code, we had no idea where the exception originated.

In a WebSphere environment, users are supposed to throw a ServiceBusinessException (this is an IBM created exception class). This tells the WebSphere framework that a backend application error occurred. With our application however, we frequently saw that this exception didn’t show where the error originated. By reviewing lots of log files, I noted that sometimes the stack trace did point to the source code line where the exception was thrown and sometimes it didn’t. It was most puzzling and I couldn’t figure out what was going on. At the same time, I did notice that whenever a Java IllegalArgumentException was thrown, a complete stack trace was presented.

Using SoapUI, I fed the application some bad data on purpose. I knew exactly which ServiceBusinessException was being thrown within the application. The line of code looked something like this:

throw new ServiceBusinessException(“Some error message.”); 

I had a wild idea. Let’s replace that line and throw an IllegalArgumentException and see if we would get a full stack trace or a stack trace that was missing the crucial lines. If we got a good stack trace, this would infer something amiss within ServiceBusinessException. If we still got a bad stack trace, this would imply something in our code was messing up the stack or the exception handler. So the new line of code looked like this:

throw new IllegalArgumentException(“Some error message.”); 

I ran the test. The stack trace that appeared in the log file was complete! So I now had some evidence that showed the culprit to be the ServiceBusinessException itself and not something in the application. So within WID (the WebSphere modified version of Eclipse) I placed the cursor on the word ‘IllegalArgumentException’ and pressed the F3 key (“Open Declaration”). Since I had installed the JAD (Java Decompiler) plugin, WID was able to decompile the IllegalArgumentException.class into real Java source code. What I saw was the following code:

public IllegalArgumentException(String s) {
    super(s);
}

Then I did the same thing for ServiceBusinessException:

public ServiceBusinessException(Object data)
{
    if (data instanceof DataObject)
        this.data = new XMLExternalizableDataObjectHolder((DataObject)data);
  else
    this.data = data;
}

The first thing I noticed by perusing the decompiled source code was that the ServiceBusinessException constructor did not call the super() method. That did not look right to me. Was that a bug since after all, they both extended class RuntimeException? With further inspection, I noticed that ServiceBusinessException had a second constructor which did include the call to super(). It looked like this:


public ServiceBusinessException(Throwable cause)
{
    super(toString(cause), cause(cause));
    if (cause != null && cause.getClass() ==  
        com/ibm/websphere/sca/ServiceBusinessException)
    {
        // a bunch of logic goes here
    }
}

So I modified my code to force invocation of this second constructor of ServiceBusinessException and test the theory that the missing call to super() was the source of the bug. My code ended up looking like this:

IllegalArgumentException exc = new IllegalArgumentException(“Some error message.”); 
throw new ServiceBusinessException(exc);

Suddenly my stack trace looked correct. This then was the confirmation I needed to demonstrate that ServiceBusinessException had a bug in it (a missing call to super()). I don’t know how long it would have taken me to find this bug had I not had the ability to decompile the two exception classes and compare them. I am convinced, however, that it would have taken much longer than it did take.

Adding JAD and the JAD plugin to Eclipse or WID is very easy. The JAD plugin can be found at http://sourceforge.net/projects/jadclipse/ . JAD can be found at http://www.varaneckas.com/jad/.

Place the JAD decompiler (jad.exe) in a directory of your choice. In a Unix environment, you may need to make JAD executable. Place the JAD plugin (the jar file) in Eclipse plugins directory. Restart Eclipse and go to Window → Preferences → Java → JadClipse. Change the ‘Path to decompiler’ location to fully reference the jad.exe file wherever you have placed it.

The ‘class’ file association must be updated (in case it wasn’t automatically done through the plugin installation). Go to Window → Preferences → General → Editors → File Associations. For file type “.class”, add “JadClipse Class file Viewer” as the default editor.