# Tuesday, 22 February 2005
« Snapshot | Main | Stack Traces »
Eclipse is Evil

While it's been possible to start up Eclipse with IKVM for a long time, editing a Java source didn't really work. Today I decided to look into the problem. It turned out to be caused by an IllegalStateException thrown from the following method in MarkerAnnotationPreferences.java:

/**
 * Checks correct access.
 * 
 * @throws IllegalStateException if not called by {@link EditorsUI}
 * @since 3.0
 */
private static void checkAccess() throws IllegalStateException {
  StackTraceElement[] elements=  new Throwable().getStackTrace();
  if (!(elements[2].getClassName().equals(EditorsUI.class.getName())
      || elements[3].getClassName().equals(EditorsUI.class.getName())))
      throw new IllegalStateException();
}

It looks at the stack trace that the Throwable produces to ascertain if it was called by the correct method. This is obvious not very robust (as is born out by the fact that it checks two different slots in the array).

The calling method in EditorsUI.java is:

public static void useAnnotationsPreferencePage(IPreferenceStore store) {
  MarkerAnnotationPreferences.useAnnotationsPreferencePage(store);
}

A perfect candidate for inlining! Which the CLR does, of course. So the EditorsUI class didn't appear in the stack trace at all, causing checkAccess() to fail.

For the time being I added a workaround to IKVM to disable inlining for all methods in classes named org.eclipse.ui.editors.text.EditorsUI, but that's obviously a disgusting hack.

Tuesday, 22 February 2005 13:49:56 (W. Europe Standard Time, UTC+01:00)  #    Comments [3] Tracked by:
"best online tournament poker no limit internet" (best online tournament poker n... [Trackback]

Tuesday, 22 February 2005 20:25:19 (W. Europe Standard Time, UTC+01:00)
While I agree that the Eclipse code is performing some nasty checks there I don't think I agree with the implication that the stacktrace created by the VM should change based on whether the method was inlined or not. I'm not sure what is mandated by the JVM spec but the stacktrace isn't going to be very useful for a developer debugging his program if the stacktrace changes depending on whether something got inlined or optimized away by the VM...
Corey
Thursday, 24 February 2005 14:11:14 (W. Europe Standard Time, UTC+01:00)
On "Eclipse is Evil": It's odd, because that code works with any tandard JVM. The Java VMs do not inline anything in the bytecode level, they only inline in the JIT compiler but at least HotSpot is able to do such optimizations while keeping metadata that allows to map to the "standard" code structure when required (i.e., exception handling, or on-stack replacement for dynamic [de]optimization). In fact I was confident that this behavior was mandated by spec in the cases that it affects the outcome of public APIs, but checking the docs for getStackTrace(), it says "Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this throwable is permitted to return a zero-length array from this method. Generally speaking, the array returned by this method will contain one element for every frame that would be printed by printStackTrace."

Generally, like I said above Sun's VM is okay, it doesn't eat stack any frames. But IBM JDK should do that. It seems that IBM's jitter is not very smart about inlining, because when I get exception inside WebSphere, the stacktrace sometimes doesn't show line numbers (just "(Compiled Code)") even if the code contains debug info. This never happens to me with Sun's VM. I think Eclipse's hack is there for IBM JDK.

Regarding the "extreme cases" clause in the javadocs above, even Sun's VM may sometimes do that because of library optimizations: some internal J2SE APIs use pre-allocated exception objects in critical code that uses exceptions as control structures, so the cost of a throw is much smaller (no allocation and no filling of the exception), but the exception doesn't contain any trace info at all. But these special cases are caught by the APIs and should not leak to application code anyway.
Osvaldo Pinali Doederlein
Monday, 28 March 2005 00:04:21 (W. Europe Daylight Time, UTC+02:00)
If you are inling byte code, what is happening to reflection?
In your example, if you inline checkAccess, the fact that it is private does not mean that I cannot use reflection on it. Tricky and hacky but possible.

You will probably generate really odd bugs down the road if you do that kind of optimization.
Name
E-mail
Home page

I apologize for the lameness of this, but the comment spam was driving me nuts. In order to be able to post a comment, you need to answer a simple question. Hopefully this question is easy enough not to annoy serious commenters, but hard enough to keep the spammers away.

Anti-Spam Question: What method on java.lang.System returns an object's original hashcode (i.e. the one that would be returned by java.lang.Object.hashCode() if it wasn't overridden)? (case is significant)

Answer:  
Comment (HTML not allowed)  

Live Comment Preview