How to remove java..* calls while using cflow() in

2019-07-06 05:02发布

I have captured my problem in the following sample code. HelloWorld class is my source which needs to be instrumented by HelloWorldTracer aspect. My objective is to find all the method calls which are in the control flow of HelloWorld.main(). But I'm not interested in the method calls related to any types in the package java.lang.* (eg: java.lang.StringBuilder).

package com.abc;

public class HelloWorld {

    public static void main(String args[]) {
        StringBuilder str = new StringBuilder();
        str.toString();
        Sample.testMethod();
    }
}

package com.abc;

public class Sample {

    public static void testMethod()
    {
        StringBuilder str = new StringBuilder();
        str.toString(); 
    }

}


public aspect HelloWorldTracer {

    pointcut helloWorldTracker() : 
        execution(* com.sybase.HelloWorld.main(..)) && within(com.abc..*) &&  !within(HelloWorldTracer);

    pointcut methodTracker():
         cflow(helloWorldTracker()) 
         && !within(java.lang..*) && !within(HelloWorldTracer);

    Object around(): methodTracker()
    {

        System.out.println("Inside advice..." + thisJoinPointStaticPart.getSignature().toString() );
        Object o = proceed();
        return o;
    }

}

Using the poincuts mentioned above the type StringBuilder is also getting advised even though !within(java.lang..*) has been explicitly specified in methodTracker() pointcut. I also tried !within(java.lang.StringBuilder) and !execution(String java.langStringBuilder.toString(..)) as well, but in vain. Any help in restricting the types from java.lang..* from getting advised will be appreciated.

标签: java aspectj
2条回答
我欲成王,谁敢阻挡
2楼-- · 2019-07-06 05:53

I think you should use execution instead of within for this case.

pointcut methodTracker():
     cflow(helloWorldTracker()) 
     && !execution(* java.lang..*(..)) && !within(HelloWorldTracer);

methodTracker() captures all calls done from not within java.lang.*

The call to StringBuilder.toString() was done from Sample.testMethod() is therefor returned by the pointcut.

查看更多
成全新的幸福
3楼-- · 2019-07-06 05:55

Nitzan Volman's suggestion is not what you want.

First of all, in your code sample probably you want to change

execution(* com.sybase.HelloWorld.main(..))

to

execution(* com.abc.HelloWorld.main(..))

Having fixed that, you will get a lot of warnings because you are trying to advise initialization() and preinitialization() pointcuts with around() which is impossible due to compiler limitations.

Then when you change your output line to just

System.out.println(thisJoinPointStaticPart);

You will see what really happens in your code:

execution(void com.abc.HelloWorld.main(String[]))
call(java.lang.StringBuilder())
call(String java.lang.StringBuilder.toString())
call(void com.abc.Sample.testMethod())
staticinitialization(com.abc.Sample.<clinit>)
execution(void com.abc.Sample.testMethod())
call(java.lang.StringBuilder())
call(String java.lang.StringBuilder.toString())

I.e. you are not just intercepting method calls (or did you mean to catch method executions, which is not the same?), but all (well, many) sorts of joinpoints. Try this:

public aspect HelloWorldTracer {
    pointcut belowHelloWorldMain() :
        cflow(execution(* com.abc.HelloWorld.main(..)));

    pointcut methodTracker():
        belowHelloWorldMain() &&
        call(* *(..)) &&
        !call(* java.lang..*(..)) &&
        !within(HelloWorldTracer);

    Object around(): methodTracker() {
        System.out.println(thisJoinPointStaticPart);
        return proceed();
    }
}

Result:

call(void com.abc.Sample.testMethod())

Just in case you only wanted to intercept executions of (instead of calls to) your own (woven) classes anyway, it is even simpler, because then you do not need to exclude the Java classes:

public aspect HelloWorldTracer {
    pointcut belowHelloWorldMain() :
        cflow(execution(* com.abc.HelloWorld.main(..)));

    pointcut methodTracker():
        belowHelloWorldMain() &&
        execution(* *(..));

    Object around(): methodTracker() {
        System.out.println(thisJoinPointStaticPart);
        return proceed();
    }
}

Result:

execution(void com.abc.HelloWorld.main(String[]))
execution(void com.abc.Sample.testMethod())

As you can see, now even main(..) is included.

查看更多
登录 后发表回答