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))

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() {
>         --level;
>         offset();
>         System.out.println("<= " + thisJoinPoint);
>     }
> } // TraceTrace
> 
> I use 
> 
> AspectJ Compiler 1.2 built on Friday May 21, 2004 at 15:06:22 GMT
> 
> and 
> 
> java version "1.4.2_01"
> Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_01-b06)
> Java HotSpot(TM) Client VM (build 1.4.2_01-b06, mixed mode)
> 
> Thanks,
> 
> Chi-Hua
> 
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users
> 




Back to the top