[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-users] Infinite advice call problem

Robert,

The problem is twofold.  First, yes, you've got a problem
with indirect recursion.  Note that in your code there is no
_execution_ of MemoryFault's constructor within the body of
the Constructor Aspect, so !within(Constructor) isn't going
to do any restriction.

You might then be tempted to write

    after(MemoryFault mf):
        target(mf) &&
        execution(MemoryFault.new(..)) &&
        ! withincode(Object MemoryFault.clone()) { ... }

but this won't work either.  You're working with constructor
_executions_, which occur within the constructor (think of
them being "callee-side").

There are a couple of things you can do about this,
depending on what you want your program to do:

1. Change to constructor call join points, and filter out
   the offending calling points with within.  This will only
   be able to expose the object after the join point
   returns:

    after() returning (MemoryFault mf):
            call(MemoryFault.new(..))
            && ! withincode(Object MemoryFault.clone()) {
       MemoryFault other = (MemoryFault) mf.clone();
    }

2. Use cflow to stomp on even indirect recursion

    after(MemoryFault mf):
            target(mf) &&
            execution(MemoryFault.new(..)) &&
            ! cflowbelow(call(Object MemoryFault.clone())
                         && within(Constructor)) {
       MemoryFault other = (MemoryFault) mf.clone();
    }

    Note that I've stomped on the indirect recursion rather
    specifically, picking out exactly one call in the world.
    In the future, if you use AspectJ 1.1, you might use the
    new adviceexecution pointcut to pick out all advice
    executions from the Constructor aspect (This doesn't
    work in 1.1b2 because of a bug that's being fixed):

    after(MemoryFault mf):
            target(mf) &&
            execution(MemoryFault.new(..)) &&
            ! cflowbelow(adviceexecution()
                         && within(Constructor)) {
       MemoryFault other = (MemoryFault) mf.clone();
    }

    This will filter out all the join points below the
    execution of advice from Constructor.

Let me know if this doens't answer your question,

-erik

> -----Original Message-----
> From: Robert Wenner [mailto:robert@xxxxxxxxxx] 
> Sent: Tuesday, 7 January, 2003 1:14 am
> To: aspectj-users@xxxxxxxxxxx
> Subject: [aspectj-users] Infinite advice call problem
> 
> 
> Hi,
> 
> I have the problem of infinite advice calls as described in FAQ item 	
> 11.1; running the program below crashes the VM with a memory fault 
> (hence the class name).
> 
> According to the FAQ answer I could use after returning instead of 
> plain after to handle exceptions different from normal method 
> execution, or I could use !within(theAspect). Neither works for me, 
> i.e. neither changes the program behaviour.
> 
> I understand that the after returning does not have any impact on the 
> sample code as nothing is thrown. 
> But why doesnt !within work? Is this a problem due to indirect 
> recursion?
> 
> What am I missing? 
> 
> Thanks in advance,
> 
> Robert
> 
> 
> class MemoryFault {
>     public static void main(String args[]) {
>         MemoryFault mf = new MemoryFault();
>     }
> 
>     public Object clone() {
>         return new MemoryFault();
>     }
> }
> 
> aspect Constructor {
>     after(MemoryFault mf):
>         target(mf) &&
>         execution(MemoryFault.new(..)) &&
>         !within(Constructor) {
>         // System.out.println("In after() advice");
>         MemoryFault other = (MemoryFault) mf.clone();
>     }
> }