Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] cflow(within(C)) vs (within(C) || cflowbelow(within(C)) [BUGZILLA-ed]

Reference bug#74952.

Thanks for the replies. I will remember not to use cflow alone.

Chi-Hua

--- Wes Isberg <wes@xxxxxxxxxxxxxx> wrote:

> Hi all -
> 
> Some comments but no definitive answers wrt the bugs
> 
> 1) see existing code for printing join points
> 2) don't use !cflow(..)
> 3) changing precedence makes the preinitialization advice work
> 4) aspects advising themselves have to be careful
>    during instantiation...
> 
> To start with the initial concern...
> 
> The AspectJ sample code has a program that will print all join
> points.  
> The sample code (as distinct from the examples) is only available 
> via a link off the AspectJ web site publication page.  To make
> it even easier, here's a simple variant:
> 
> ---------- AllJoinPoints.java 
> 
> public class AllJoinPoints {
>     static int I = 1;
>     int j = 2*I;
>     public static void main(String[] a) {
>         try {
>             new AllJoinPoints().toString();
>             throw new Error();
>         } catch (Throwable t) {
>             System.out.println("Hello, World!");
>         }
>     }
>     static aspect A {
>         before(): execution(void main(String[])) {
>             System.out.println("This is just to say...");
>         }
>     }
> 
> }
> aspect B {
>     pointcut all() : !within(B);
>     before() : all() {
>         System.out.println("start: " + thisJoinPointStaticPart);
>     }
>     after () returning : all() && !handler(*) {
>         System.out.println("  end: " + thisJoinPointStaticPart);
>     }
> }
> ---------- 
> 
> As for the programs, I recommend no one use cflow(..) alone as a
> pointcut used by advice.  It means every join point in the world 
> has to do this dynamic check.  cflow differs from target(), args(),
> and this() in that there's no information in the join point itself
> that would tell you to skip it (e.g., this(Runnable) is 
> inapplicable in any execution join point of a class that is not
> Runnable).  And since even those possible optimizations are not 
> guaranteed, using a purely dynamic pointcut could devolve to the 
> worst case in some implementations of AspectJ, so all lone dynamic
> PCD's should be scrutinized...
> 
> To back up a bit, cflow(), target(), args() and this() are dynamic.
> You can think of a pointcut as having three components: the kinds, 
> the scopes, and any dynamic tests.  It is fair to ask for all 
> kinds by leaving out call, execution, etc., and for all scopes 
> by leaving out within, etc., but "finding all {other} join points" 
> is about the only use-case for doing both.
> 
> (And if I haven't convinced folks on style grounds, just look
> at what the implementation does *smile*)
> 
> Now, to address what's going wrong (though not completely)...
> 
> A hint regarding the missing after-advice on the preinitialization 
> join point: it re-appears if it's of a lower precedence (and 
> hence runs before) the advice in the aspect that's being 
> initialized.  E.g.,
> 
> aspect TraceTrace {
>   // our after advice runs before TraceClass advises itself...
>   declare precedence : TraceClass, TraceTrace;
>   pointcut pc() : within(TraceClass);
>   before() : pc() {
>     System.out.println("-> " + thisJoinPoint);
>   }
>   after() returning : pc() {
>     System.out.println("<- " + thisJoinPoint);
>   }
> }
> 
> Finally, in the original code, the singleton aspect is being
> being instantiated in the static initializer of the aspect 
> class when something blows up.  It so happens that the cflow 
> stuff is set up in the class static preinitialization so that 
> it's usable but probably not correct; since it returns no/false
> by default, !cflow(..) would run by default, in every join point...
> 
> There is a bug or two in here; would anyone care to submit it?
> 
> Hope this helps -
> Wes
> 
> 
> > ------------Original Message------------
> > From: Stephanie <stephaniechc-newsaj@xxxxxxxxx>
> > To: aspectj-users@xxxxxxxxxxx
> > Date: Thu, Sep-23-2004 2:25 PM
> > Subject: [aspectj-users] cflow(within(C)) vs (within(C) ||
> cflowbelow(within(C))
> >
> > I am new to AspectJ and is just trying to understand what each kind
> of
> > pointcut matches. So I wrote a simple class, SomeClass, and a
> simple
> > aspect, TraceClass, and was hoping that the aspect would print out
> all
> > the join points in SomeClass. To avoid infinite recursion, in
> > TraceClass I used "!cflow(within(Trace*))" as the pointcut.
> However, I
> > was not getting any output. Though "!(within(Trace*) ||
> > cflowbelow(within(Trace*)))" worked as I expected (printing
> something).
> > (From the post "cflow ( x()) && !cflowbelow( x()) " confusesme" I
> > gathered that cflow(x()) does not equal to (x() ||
> cflowbelow(x())).
> > However, I still don't understand why my test doesn't work).
> > 
> > class SomeClass 
> > {
> >     static public void main (String [] args) {
> >     }
> > } // SomeClass
> > 
> > aspect TraceClass {
> > 
> >     // members
> >     static private int level = 0;
> > 
> >     static private void offset() {
> >         int i;
> >         for (i = 0; i < level; ++i) {
> >             System.out.print("  ");
> >         }
> >     } // offset
> > 
> >     pointcut pc() : 
> >         !cflow(within(Trace*))
> > //        !(within(Trace*) || cflowbelow(within(Trace*)))
> >         ;
> >     before () : pc() {
> >         offset();
> >         System.out.println("-> " + thisJoinPoint);
> >         ++level;
> >     }
> >     after  () : pc() {
> >         --level;
> >         offset();
> >         System.out.println("<- " + thisJoinPoint);
> >     }
> > } // TraceClass
> > 
> > In order to figure out what is happening with TraceClass, I added a
> > third class, TraceTrace, which prints everything happen
> > "within(TraceClass)". Again, when TraceClass used "!(within(Trace*)
> ||
> > cflowbelow(within(Trace*)))" it worked. However, when TraceClass
> used
> > "!cflow(within(Trace*))", the output was
> > 
> > => staticinitialization(TraceClass.<clinit>)
> >   => set(int TraceClass.level)
> >   <= set(int TraceClass.level)
> >   => preinitialization(TraceClass())
> >     => initialization(TraceClass())
> >       => execution(TraceClass())
> >       <= execution(TraceClass())
> >     <= initialization(TraceClass())
> >   <= staticinitialization(TraceClass.<clinit>)
> > 
> > The after advice for preinitialization was never executed and no
> trace
> > for SomeClass was printed.
> > 
> > aspect TraceTrace {
> > 
> >     // members
> >     static private int level = 0;
> > 
> >     static private void offset() {
> >         int i;
> >         for (i = 0; i < level; ++i) {
> >             System.out.print("  ");
> >         }
> >     } // offset
> > 
> >     pointcut pc() : within(TraceClass);
> >     before () : pc() {
> >         offset();
> >         System.out.println("=> " + thisJoinPoint);
> >         ++level;
> >     }
> >     after  () : pc() {
> 
=== message truncated ===



Back to the top