Community
Participate
Working Groups
Build R2.0 From eclipse.tools (c.dodd@insightbb.com) When compiling in 1.4 compliant mode, the following code: ============== package p; public class X { public static void main(String[] args) { new X(); System.out.println("SUCCESS"); } Woof woof_1; public class Honk { Integer honks; } public class Meow { Honk honk_1; } public class Woof { Meow meow_1; } public void setHonks(int num) { // This is the line that causes the VerifyError woof_1.meow_1.honk_1.honks = new Integer(num); // Here is equivalent code that does not cause the error. // Honk h = woof_1.moo_1.meow_1.honk_1; // h.honks = new Integer(num); } } ============== The following verification error is thrown at runtime: java.lang.VerifyError: (class: p/X, method: setHonks signature: (I)V) Incompatible type for getting or setting field Exception in thread "main"
javap -c on #setHonks indeed indicates something went wrong: Method void setHonks(int) 0 aload_0 1 getfield #32 <Field p.X.Woof woof_1> 4 getfield #38 <Field p.X.Meow meow_1> 7 getfield #44 <Field null> // -------------------> should be honk_1 10 new #46 <Class java.lang.Integer> 13 dup 14 iload_1 15 invokespecial #48 <Method java.lang.Integer(int) 18 putfield #52 <Field java.lang.Integer honks> //-> should be X$Honk member 21 return -------- Now this is only the way javap prints the issue, and our disassembler doesn't quite reflect the same issue: public void setHonks(int arg); /* Method descriptor #30 (I)V */ Code attribute: /* Stack: 4, Locals: 2 */ 0 aload_0 1 getfield #32 <Field p.X#woof_1 p.X.Woof> 4 getfield #38 <Field p.X$Woof#meow_1 p.X.Meow> 7 getfield #44 <Field p.X$Honk#honk_1 p.X.Honk> 10 new #46 java.lang.Integer 13 dup 14 iload_1 15 invokespecial #48 <Constructor java.lang.Integer(int arg)> 18 putfield #52 <Field p.X$Honk#honks java.lang.Integer> 21 return
Indeed, javap has a bug, since even if disassembling javac compiled bytecodes, which run ok, prints: Method void setHonks(int) 0 aload_0 1 getfield #7 <Field p.X.Woof woof_1> 4 getfield #8 <Field p.X.Meow meow_1> 7 getfield #9 <Field p.X.Honk honk_1> 10 new #10 <Class java.lang.Integer> 13 dup 14 iload_1 15 invokespecial #11 <Method java.lang.Integer(int)> 18 putfield #12 <Field java.lang.Integer honks> //-> should be X$Honk member 21 return
The declaring class of the 1.4 field access to #honk_1 should read X$Meow, but incorrectly targets X$Honk. Bug found in the #analyzeAssignment loop for other bindings, it did consider field at i-1 instead of field at i-2 when retrieving the lastReceiverType. Now the bytecode generated is correctly outputted as: <Field p.X$Meow#honk_1 p.X.Honk> public void setHonks(int arg); /* Method descriptor #30 (I)V */ Code attribute: /* Stack: 4, Locals: 2 */ 0 aload_0 1 getfield #32 <Field p.X#woof_1 p.X.Woof> 4 getfield #38 <Field p.X$Woof#meow_1 p.X.Meow> 7 getfield #44 <Field p.X$Meow#honk_1 p.X.Honk> 10 new #46 java.lang.Integer 13 dup 14 iload_1 15 invokespecial #48 <Constructor java.lang.Integer(int arg)> 18 putfield #54 <Field p.X$Honk#honks java.lang.Integer> 21 return Fixed in latest.
Fixed in HEAD stream.
Fixed
Verified.
Verified
Verified in 2.1 M1