Bug 170044 - [ltw] @Pointcut annotated methods should not be available to be woven
Summary: [ltw] @Pointcut annotated methods should not be available to be woven
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: LTWeaving (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: Neale Upstone CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-01-09 22:26 EST by Ramnivas Laddad CLA
Modified: 2013-06-24 11:06 EDT (History)
2 users (show)

See Also:


Attachments
Minimal project showing problem (1.45 KB, application/octet-stream)
2009-03-30 18:11 EDT, Neale Upstone CLA
no flags Details
Patch to run scenario under ajc165 test suite (2.79 KB, patch)
2009-04-13 16:27 EDT, Neale Upstone CLA
no flags Details | Diff
mylyn/context/zip (14.79 KB, application/octet-stream)
2009-04-13 16:28 EDT, Neale Upstone CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ramnivas Laddad CLA 2007-01-09 22:26:36 EST
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).
Comment 1 Ramnivas Laddad CLA 2007-01-09 22:58:41 EST
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.
Comment 2 Neale Upstone CLA 2009-03-30 09:27:35 EDT
Feel free to assign this to me.  I've been lurking in showWeaveInfo
Comment 3 Neale Upstone CLA 2009-03-30 18:11:37 EDT
Created attachment 130327 [details]
Minimal project showing problem
Comment 4 Neale Upstone CLA 2009-03-30 19:41:03 EDT
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.
Comment 5 Neale Upstone CLA 2009-04-13 16:05:09 EDT
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?
Comment 6 Neale Upstone CLA 2009-04-13 16:27:56 EDT
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.
Comment 7 Neale Upstone CLA 2009-04-13 16:28:01 EDT
Created attachment 131705 [details]
mylyn/context/zip
Comment 8 Andrew Clement CLA 2009-04-13 18:33:17 EDT
> 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).
Comment 9 Andrew Clement CLA 2009-04-13 22:00:02 EDT
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!)
Comment 10 Neale Upstone CLA 2009-04-14 04:03:06 EDT
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.
Comment 11 Andrew Clement CLA 2009-04-14 12:21:26 EDT
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.
Comment 12 Neale Upstone CLA 2009-04-14 15:10:12 EDT
(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.
Comment 13 Andrew Clement CLA 2013-06-24 11:06:06 EDT
unsetting the target field which is currently set for something already released