Project: AspectJ
Bug 101047 Weaver produces wrong local variable table bytecode
Reported: 2005-06-21 10:13:24 | Status: resolved fixed

AspectJ version: DEVELOPMENT (also observed in 1.2.1) When weaving with a before or after advice, the generated local variable table will, on branch instructions, offset the "length" field of a local variable wrongly by one instruction. Also, the weaver will mix up local variables with the same name, thus violating the java VM specification: // Test.aj aspect Test { before() : ( execution(* Foo.foo(..) ) ) { System.out.println("before"); } // Foo.java public class Foo { private String myString = "A String"; public static void main(String[] args) { new Foo().foo(); } private void foo() { String myLocal = myString; if (myLocal.endsWith("X")) { String local1 = "local1"; System.out.println(local1); } else if (myLocal.endsWith("Y")) { String local2 = "local2"; System.out.println(local2); } else { String local1 = "local3"; System.out.println(local1); } } } --- We compilw with ajc -sourceroots . and dumps Foo with javap: javap -c -l -s -private Foo .... .... private void foo(); Signature: ()V Code: 0: invokestatic #65; //Method Test.aspectOf:()LTest; 3: invokevirtual #68; //Method Test.ajc$before$Test$1$f0485e90:()V 6: aload_0 7: getfield #15; //Field myString:Ljava/lang/String; 10: astore_1 11: aload_1 12: ldc #30; //String X 14: invokevirtual #36; //Method java/lang/String.endsWith: (Ljava/lang/String;)Z 17: ifeq 33 20: ldc #38; //String local1 22: astore_2 23: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream; 26: aload_2 27: invokevirtual #50; //Method java/io/PrintStream.println: (Ljava/lang/String;)V 30: goto 65 33: aload_1 34: ldc #52; //String Y 36: invokevirtual #36; //Method java/lang/String.endsWith: (Ljava/lang/String;)Z 39: ifeq 55 42: ldc #54; //String local2 44: astore_2 45: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream; 48: aload_2 49: invokevirtual #50; //Method java/io/PrintStream.println: (Ljava/lang/String;)V 52: goto 65 55: ldc #56; //String local3 57: astore_2 58: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream; 61: aload_2 62: invokevirtual #50; //Method java/io/PrintStream.println: (Ljava/lang/String;)V 65: return LineNumberTable: line 7: 6 line 8: 11 line 9: 20 line 10: 23 line 11: 33 line 12: 42 line 13: 45 line 15: 55 line 16: 58 line 18: 65 LocalVariableTable: Start Length Slot Name Signature 6 60 0 this LFoo; 11 55 1 myLocal Ljava/lang/String; 45 12 2 local2 Ljava/lang/String; 23 43 2 local1 Ljava/lang/String; We see that the two occurences of the "local1" variable erroneously have been combined into one entry, starting at byte 23 and ending at byte 66. This is obviously wrong, since "local1" has no value in the "local2" block. Secondly, the "local2" variable end is wrongly offset by one instruction offset.

Files changed in fix:
bcel-builder/src/org/aspectj/apache/bcel/generic/MethodGen.java