JVM hack implementations, and why I love Java

During a Java debug session today, I was investigating an exception and noticed that its cause was set to itself; effectively leading to an infinite stacktrace (or so I thought).

When I added a watch on exception.getCause(), this returned null though, so I initially assumed this was a bug in my IDE (I'm using a beta release of IDEA 5.0). However, a quick check of the source-code of Throwable disproved that initial assumption. As it turns out, this problem is caused by a JVM hack implementation.

Take a look at the excerpt from Throwable below:

  /**
   * The throwable that caused this throwable to get thrown, or null if this
   * throwable was not caused by another throwable, or if the causative
   * throwable is unknown.  If this field is equal to this throwable itself,
   * it indicates that the cause of this throwable has not yet been
   * initialized.
   *
   * @serial
   * @since 1.4
   */
  private Throwable cause = this;

  public Throwable getCause() {
      return (cause==this ? null : cause);
  }

  public synchronized Throwable initCause(Throwable cause) {
      if (this.cause != this)
          throw new IllegalStateException("Can't overwrite cause");
      if (cause == this)
          throw new IllegalArgumentException("Self-causation not permitted");
      this.cause = cause;
      return this;
  }
It turns out that self-causation is the default state; indicating that the cause has not yet been initialized. In other words, it's nothing but a hack to save the developer from either adding a causeInitialized boolean to Throwable, or (if they really felt they need to save those 4 bytes), doing something like
  private static Throwable NOT_INITIALIZED =
             new Throwable("CAUSE NOT INITIALIZED", null);
    
  private Throwable cause = NOT_INITIALIZED;
Now from a runtime-perspective, this hack really doesn't matter as cause is private and the this initial value is never returned to the user. Unfortunately from a debug-perspective, this implementation is utterly confusing.

So why do I still say I love Java? Because, unlike .NET for instance, I have access to the source-code in moments like this. Language-wise, I actually prefer C# over Java. Library-wise, I also tend to favor the .NET implementations over their Java counterparts. But with .NET, if something works somewhat differently from what I would expect, I don't have the option of checking the actual implementation. To me, this is a BIG DEAL. Having the source available is not only helpful in situations like this, but it's also a tremendous aid when you truly want to grok an API.

And yes, I'm aware of the existence of Rotor and decompilers, but

  1. Rotor is an incomplete implementation, lacking all of WinForms for instance.
  2. Decompilation is not perfect and sometimes leads to awkward looking code.
  3. Checking code from either Rotor or decompiling a class tends to not be integrated in VS.NET, so I'm forced to leave the IDE for tasks like this.
  4. .NET decompilers typically show only one decompiled method at a time (the ones I've tried did this anyway) instead of the full class, leading to a more fragmented view of the code.
  5. Decompiled code lacks comments and sometimes even lacks the original variable-names.

There's been some dialog going on for over a year now about open-sourcing Java, but as far as I'm concerned, Java's already open-source enough. I just wish .NET would follow Java's example on this aspect as well. I don't need a license to allow me to change the source, but it sure would be nice if Microsoft would surprise me and include the source in .NET 2.0...

TrackBack URL for this entry: http://www.hutteman.com/scgi-bin/mt/mt-tb.cgi/190
Comments

If you use Lutz Roeder's .NET Reflector, you can see all the source code (reverse compiled) from the .NET DLLs. The decompilation is good enough that I've been able to understand some tough corner cases without the source code. However, code comments would be nice to explain the 'why', since reverse compilation just gives the 'what', but no 'why'. For key frameworks like this, I completely agree with your position - source access is critical to the success of your app.

Posted by Doug de la Torre at June 6, 2005 1:47 PM

i hate java! makes me wanna rip something apart

Posted by dre at June 14, 2005 3:40 PM

I also really like Reflector. It produces readable code to me, for sure, and as a bonus is a clickable, browsable repository. When I see a reference to a function, I can just click on it to get there. It has a back button just like a browser, as well.

There's also a plugin that lets you decompile an entire assembly through Reflector into a set of files, allowing you to grep the code if you want.

Really, I couldn't imagine source code for Java as being a big enough plus to compensate for its drawbacks. To be honest, I actually don't see it as a plus at all, as I usually prefer to browse my own libraries with Reflector instead of opening the source code files.

Posted by Steve at June 17, 2005 10:46 AM

What about J#? Isn't that a .NET-enabled Java derivative?

Posted by Randall at June 27, 2005 9:07 PM

Take a look at rotor. The implementation of the BCL is pretty consistent with the shipping code. However there is not a 2.0 version yet.

Posted by Don at July 22, 2005 4:11 PM
This discussion has been closed. If you wish to contact me about this post, you can do so by email.