Community
Participate
Working Groups
AspectJ version: 1.2.1 (also observed in aspectj-DEVELOPMENT) java version "1.4.2_07" When debugging java code woven with an "around" advice with proceed, it looks like the LocalVariableTable information gets lost during the weaving. Example code: // 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; System.out.println(myLocal); // breakpoint here } } // Test.aj aspect Test { void around() : ( execution(* Foo.foo(..) ) ) { System.out.println("before"); proceed(); System.out.println("after"); } } We compiled with ajc 1.2.1: ajc -g -preserveAllLocals -sourceroots . When running Foo in the Eclipse 3.1.0 debugger and setting a breakpoint at the "System.out.println(myLocal);" line, the debugger "Variables" window is empty. Also, disassembling with javap shows that the LocalVariableTable is empty in the generated foo_aroundBody0 method : > javap -c -l -s -private Foo private static final void foo_aroundBody0(Foo); Signature: (LFoo;)V Code: 0: aload_0 1: getfield #15; //Field myString:Ljava/lang/String; 4: astore_1 5: aload_1 6: ldc #30; //String X 8: invokevirtual #36; //Method java/lang/String.endsWith: (Ljava/lang/String;)Z 11: ifeq 27 14: ldc #38; //String local1 16: astore_3 17: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream; 20: aload_3 21: invokevirtual #50; //Method java/io/PrintStream.println: (Ljava/lang/String;)V 24: goto 37 27: ldc #52; //String local2 29: astore_3 30: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream; 33: aload_3 34: invokevirtual #50; //Method java/io/PrintStream.println: (Ljava/lang/String;)V 37: return LineNumberTable: line 7: 0 line 8: 5 line 9: 14 line 10: 17 line 12: 27 line 13: 30 line 15: 37
I have started looking into this. Obviously, the org.aspectj.weaver.bcel.ShadowRange does not copy the LocalVariableTags, see the comment // XXX destroying local variable info Copying the old instruction handle to the new instruction handle actually generates a LocalVariableTable for the woven class, but there is another problem: When the woven code contains branches, the LazyMethodGen.packBody() method seem to generate wrong start_pc and length indexes. I'll look further into this
Adding M4 target milestone as per discussion in Oslo...
After a few investigations, it turns out that it is safe to retarget local variable tags when extracting a whole block (method execution, cons execution etc..), but not when weaving around advice at the statement level inside a block (eg. get/set/call). I've updated ShadowRange to reflect this. If the new logic fails, the symptom you well see is a VerifyError with "invalid local variable index: <some number>". When I compile: class Foo { static int x; private String myString = "A String"; public static void main(String[] args) { new Foo().foo(); AroundCasting.main(new String[0]); } public void foo() { String myLocal = myString; x = 5; System.out.println(myLocal); // breakpoint here bar(x); } public void bar(int y) {} } // Test.aj aspect Test { void around() : ( execution(* Foo.foo(..) ) ) { int y = 4; System.out.println("before"); proceed(); System.out.println("after"); } } I now get the output: private static final void foo_aroundBody0(Foo); Code: Stack=2, Locals=2, Args_size=1 0: aload_0 1: getfield #17; //Field myString:Ljava/lang/String; 4: astore_1 5: iconst_5 6: putstatic #38; //Field x:I 9: getstatic #44; //Field java/lang/System.out:Ljava/io/PrintStream; 12: aload_1 13: invokevirtual #50; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 16: aload_0 17: getstatic #38; //Field x:I 20: invokevirtual #54; //Method bar:(I)V 23: return LocalVariableTable: Start Length Slot Name Signature 0 24 0 this LFoo; 5 19 1 myLocal Ljava/lang/String; LineNumberTable: line 22: 0 line 23: 5 line 24: 9 line 25: 16 line 26: 23 (note the correctly preserved locals and line numbers). I'm committing this change, but want to wait and see this do the right thing in the AJDT debugger before closing out the bug.
Required one final change in the weaver to cope with our remapping of locals to wide slots. Finally you can debug inlined around advice methods and see all locals in the debugger (see screenshot in the attachment). Fix will be available in next published AspectJ build, and incorporated into AJDT next Monday.
Created attachment 27852 [details] screenshot of debugging inlined around advice w. local vars