Community
Participate
Working Groups
The -showWeaveInfo shows that @AspectJ advice being selected by execution(...) pointcuts. The execution itself is fine (advice isn't actually applied). Here is the minimum setup: // bug/Main.java package bug; public class Main { public static void main(String[] args) { } } // tracing.Tracing.java package tracing; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class Tracing { @Pointcut("execution(* *.*(..))") public void traced() {} @Before("traced()") public void trace(JoinPoint.StaticPart jpsp) { System.out.println("Entering " + jpsp.getSignature().toShortString()); } } META-INF/aop.xml: <aspects> <aspect name="tracing.Tracing"/> <weaver options="-showWeaveInfo"/> </aspects> > java -javaagent:<path-to>/aspecthweaver.jar bug.Main [AppClassLoader@1f12c4e] weaveinfo Join point 'method-execution(void bug.Main.main(java.lang.String[]))' in Type 'bug.Main' (Main.java:10) advised by before advice from 'tracing.Tracing' (Tracing.java) [AppClassLoader@1f12c4e] weaveinfo Join point 'method-execution(void tracing.Tracing.traced())' in Type 'tracing.Tracing' (Tracing.java:11) advised by before advice from 'tracing.Tracing' (Tracing.java) Entering Main.main(..) The second weaveInfo message is in error. Execution itself is fine (otherwise, we would run into infinite recursion).
There is a bug lurking here, although not perhaps the exact one I described. The -showWeaveInfo is pointing to the method-execution(...) join point. Since I am not exercising traced() as a method, the join point never matches at runtime. I guess this kind of possibility is new with @AspectJ (two kinded join point shadows associated with a single program element). So the real bug seems to be the asymmetry between what AJDT and LTW shows. Now convert the same project to an AspectJ project. AJDT does *not* show that (the method execution shadow of) the traced() method is being advised.
Feel free to assign this to me. I've been lurking in showWeaveInfo
Created attachment 130327 [details] Minimal project showing problem
So, firstly. Does traced() get woven in this scenario? We need to cause traced() to be executed to find out. The following change does the trick, and gives us the expected recursive call: @Pointcut("execution(* *.*(..)) && if()") public static boolean traced() { return true;} Now, if we convert the project to AJ, we get only the single weaveInfo message: Join point 'method-execution(void bug.Main.main(java.lang.String[]))' in Type 'bug.Main' (Main.java:4) advised by before advice from 'tracing.Tracing' (Tracing.java:15) [with runtime test] Main.java bug170044/src/bug line 4 Java Problem When we run it... mmm... It hasn't been woven. There is a difference in behaviour between AJDT and LTW, as suggested in comment #1.
As much as anything this is an opportunity for me to educate myself, so I'm thinking aloud here. Why is the behaviour of LTW different from AJDT? The LTW scenario: - javac compiles Tracing.java to give annotations, but does no weaving. - LTW then sees Tracing.class as both a source of aspects and a target for weaving, and weaves it Under AJDT: - ajc compiles Tracing.java - ajc weaves Tracing.class, but doesn't weave the joinpoint The woven result differs! As we're not saying !within(tracing.Tracing) in our pointcut, then I assume that LTW is behaving correctly, and AJC is getting it wrong. Does anyone disagree?
Created attachment 131704 [details] Patch to run scenario under ajc165 test suite If anyone wants to single step this, then this'll allow you to run as Junit test. I'd need to get further into AJC's internals, which I'm sure will come as I delve deeper.
Created attachment 131705 [details] mylyn/context/zip
> As we're not saying !within(tracing.Tracing) in our pointcut, then I assume > that LTW is behaving correctly, and AJC is getting it wrong. Does anyone > disagree? I disagree. traced() is a special method that happens to be something to hang the pointcut annotation off and a place to 'stuff' the if code. You can't weave pointcuts in code style, so you shouldn't be able to weave that. It doesn't have a counterpart in code style but is roughly like saying pointcut p(): within(*) && if(true); before(): p() { } that the advice p() should apply inside the body of if(true). So if this is happening then the weaver should be actively looking for and ignoring @Pointcut annotated methods, the way it must be ignoring methods having advice annotations (since they are adviceexecution jps and not normal method execution jps).
pointcut declarations in code style don't manifest as methods in the compiled code - although a special ajc$ method is generated to contain any if() related test if there is such a thing. In order to exclude the annotation style method representing a pointcut from weaving (since it won't be prefixed ajc$ and automatically ignored) we perhaps need some kind of check in BcelClassWeaver.match() which currently does the check for 'if method is advice then create adviceexecution shadow rather than methodexecution shadow' - but the check as to whether it is a annotation style pointcut method will need to be optimal, i hope we don't need to dig for annotations, but i guess we need to check what it does for annotation style advice at the moment and do something similar... (actually bcelclassweaver.match looks overdue a rewrite - just on looking at that code quickly it seems to be it ought to be able to differentiate at a higher level between a class and an aspect and if not in an aspect don't keep checking if every single method might be an advice, when none of them can be!)
Okay. That nails what the problem is, so I've updated the summary text. Andy, I'll leave this one to you for now, if you're thinking a re-write is in order. If I get a chance I'll update my test patch with a failing test. I've also just checked the documentation, and I can see how where some of the ambiguity comes from. The @AspectJ docs build on things like Appendix B of the prog guide, where it would be useful to give code- and annotation-style examples, for example. I just can't bring myself to raise an enhancement to merge the docs, even though I do think I'd prefer them that way :) Short term, I think that when this bug IS fixed, a note could be added to http://www.eclipse.org/aspectj/doc/released/adk15notebook/ataspectj-pcadvice.html#d0e3729 to clarify that @Pointcut methods cannot be joinpoints. Another question this brings up is: can @Pointcut contain joinpoints? e.g. weaving call advice on methods called from within the body.
thanks for the write up of your findings Neale. I will take a look when I get a chance - currently struggling with a hideous itd problem. > Another question this brings up is: can @Pointcut contain joinpoints? > e.g. weaving call advice on methods called from within the body. I say no, they aren't join points for code style if() statements so they shouldn't be for annotation style either. I can just imagine us getting into trouble invoking advice whilst running if() code.
(In reply to comment #11) > > Another question this brings up is: can @Pointcut contain joinpoints? > > e.g. weaving call advice on methods called from within the body. > > I say no, they aren't join points for code style if() statements so they > shouldn't be for annotation style either. I can just imagine us getting into > trouble invoking advice whilst running if() code. > Ok. I think that fleshes out the spec then. The sort of use case that may get hit would be advised using execution, not call anyway. e.g. I can imagine an condition based on some call that had around advice for caching or synchronisation.
unsetting the target field which is currently set for something already released