Community
Participate
Working Groups
I discovered this on 3.1, but it still appears to be broken as of the November 16th 3.2 integration build (I20051116-1332). Compiled by javac 1.5 or jikes 1.21, this program runs fine on java 1.4 or 1.5; compiled by JDT it reports: "java.lang.VerifyError: (class: Derived, method: <init> signature: (Z)V) Incompatible type for getting or setting field". public abstract class Base { protected Base twin; } public class Derived extends Base { public Derived(boolean flag) { if (flag) { twin = new Derived(false); twin.twin = this; } } public static void main(String[] args) throws Throwable { System.out.println(new Derived(true)); } } Here is the code (via javap) of Derived's constructor: Javac version: public Derived(boolean); Code: 0: aload_0 1: invokespecial #1; //Method Base."<init>":()V 4: iload_1 5: ifeq 28 8: aload_0 9: new #2; //class Derived 12: dup 13: iconst_0 14: invokespecial #3; //Method "<init>":(Z)V 17: putfield #4; //Field twin:LBase; 20: aload_0 21: getfield #4; //Field twin:LBase; 24: aload_0 25: putfield #5; //Field Base.twin:LBase; 28: return JDT version: public Derived(boolean); Code: 0: aload_0 1: invokespecial #8; //Method Base."<init>":()V 4: iload_1 5: ifeq 28 8: aload_0 9: new #1; //class Derived 12: dup 13: iconst_0 14: invokespecial #11; //Method "<init>":(Z)V 17: putfield #13; //Field twin:LBase; 20: aload_0 21: getfield #13; //Field twin:LBase; 24: aload_0 25: putfield #13; //Field twin:LBase; 28: return Except for the numbering of the constant pool entries, which doesn't matter, the only difference is at offset 25 (the storing of this into twin.twin). The javac version references a FieldInfo for "Base.twin" while the JDT version references a FieldInfo for "twin" (unqualified, which I think implies the class being disassembled, i.e. Derived). The compiler probably knows that 'twin' contains a Derived because it was just set to the result of 'new Derived' at offset 9. But the verifier isn't that smart, and only knows that an object of type Base was pushed at 21. And it doesn't like you attempting to access a field of Derived from an instance of Base.
This comes from the test line in 832 org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference. If compiled with a target lower than 1.4 or a compliance lower than 1.4, it works fine.
The compiler is getting fooled by the fact the two fields in sequence are denoting the same binding. We have checked for lastField == firstField, and then believe we are processing the first field portion. We should use index instead of binding comparison.
Added ConformTest#test248. Released fix both in 3.1.2 and 3.2 streams (3.0 doesn't seem impacted).
Verified for 3.2M4 in I20051212-2000
Verified for 3.1.2 in M20060109-0800.