Community
Participate
Working Groups
Reference: "cflow(within(C)) vs (within(C)||cflowbelow(within(C)) in aspectj-users mailing list. The aspect TraceClass below doesn't print any message when the pointcut is defined to "!cflow(within(Trace*))". The other defintion "!(within(Trace*) || cflowbelow(within(Trace*)))" works fine. Wes Isberg in his reply explained that cflow should never be used alone but he thought "there is a bug or two in here" 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 try to figure out what is happening within TraceClass, I added a second aspect, TraceTrace, just to trace TraceClass. 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 Here is what TraceTrace prints when TraceClass uses "!cflow(within(Trace*))" => 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 is not executed for preinitialization.
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)
Ok. There is a real bug here. It is to do with how cflow entry is applied to preinitialization join points. We manage the cflow with a counter at various join points we will check this counter and if the number is >0 we are in a particular cflow. We apply logic at the top of the cflow to increment and decrement the counter around the join point that matches the pointcut inside the cflow() statement. This example program produces a class file that doesn't always decrement the counter when it should. The problem is actually because when working with the preinitialization shadow it is in an odd state in that it contains a branch that jumps off the end of the shadow, when in fact all branches inside it should jump to the end of the shadow. Because it doesn't exit normally, we fail to apply the 'counter decrement' logic correctly. The fix is to attach a NOP to the end of the preinitialization shadow before weaving - the branches inside the shadow then jump to this NOP rather than off the end of the shadow. We can then apply the 'counter decrement' logic (which is actually woven in as after() advice). Without the fix, the output is only a few lines long, missing all sorts of join points. With the fix in place, the program outputs this :) => staticinitialization(TraceClass.<clinit>) => set(int TraceClass.level) <= set(int TraceClass.level) => preinitialization(TraceClass()) <= preinitialization(TraceClass()) => initialization(TraceClass()) => execution(TraceClass()) <= execution(TraceClass()) <= initialization(TraceClass()) <= staticinitialization(TraceClass.<clinit>) => execution(ADVICE: void TraceClass.ajc$before$TraceClass$1$346234(JoinPoint)) => call(void TraceClass.offset()) => execution(void TraceClass.offset()) => get(int TraceClass.level) <= get(int TraceClass.level) <= execution(void TraceClass.offset()) <= call(void TraceClass.offset()) => get(PrintStream java.lang.System.err) <= get(PrintStream java.lang.System.err) => call(java.lang.StringBuffer(String)) <= call(java.lang.StringBuffer(String)) => call(StringBuffer java.lang.StringBuffer.append(Object)) <= call(StringBuffer java.lang.StringBuffer.append(Object)) => call(String java.lang.StringBuffer.toString()) <= call(String java.lang.StringBuffer.toString()) => call(void java.io.PrintStream.println(String)) -> staticinitialization(WhatsGoingOn.<clinit>) <= call(void java.io.PrintStream.println(String)) => get(int TraceClass.level) <= get(int TraceClass.level) => set(int TraceClass.level) <= set(int TraceClass.level) <= execution(ADVICE: void TraceClass.ajc$before$TraceClass$1$346234(JoinPoint)) => execution(ADVICE: void TraceClass.ajc$after$TraceClass$2$346234(JoinPoint)) => get(int TraceClass.level) <= get(int TraceClass.level) => set(int TraceClass.level) <= set(int TraceClass.level) => call(void TraceClass.offset()) => execution(void TraceClass.offset()) => get(int TraceClass.level) <= get(int TraceClass.level) <= execution(void TraceClass.offset()) <= call(void TraceClass.offset()) => get(PrintStream java.lang.System.err) <= get(PrintStream java.lang.System.err) => call(java.lang.StringBuffer(String)) <= call(java.lang.StringBuffer(String)) => call(StringBuffer java.lang.StringBuffer.append(Object)) <= call(StringBuffer java.lang.StringBuffer.append(Object)) => call(String java.lang.StringBuffer.toString()) <= call(String java.lang.StringBuffer.toString()) => call(void java.io.PrintStream.println(String)) <- staticinitialization(WhatsGoingOn.<clinit>) <= call(void java.io.PrintStream.println(String)) <= execution(ADVICE: void TraceClass.ajc$after$TraceClass$2$346234(JoinPoint)) => execution(ADVICE: void TraceClass.ajc$before$TraceClass$1$346234(JoinPoint)) => call(void TraceClass.offset()) => execution(void TraceClass.offset()) => get(int TraceClass.level) <= get(int TraceClass.level) <= execution(void TraceClass.offset()) <= call(void TraceClass.offset()) => get(PrintStream java.lang.System.err) <= get(PrintStream java.lang.System.err) => call(java.lang.StringBuffer(String)) <= call(java.lang.StringBuffer(String)) => call(StringBuffer java.lang.StringBuffer.append(Object)) <= call(StringBuffer java.lang.StringBuffer.append(Object)) => call(String java.lang.StringBuffer.toString()) <= call(String java.lang.StringBuffer.toString()) => call(void java.io.PrintStream.println(String)) -> execution(void WhatsGoingOn.main(String[])) <= call(void java.io.PrintStream.println(String)) => get(int TraceClass.level) <= get(int TraceClass.level) => set(int TraceClass.level) <= set(int TraceClass.level) <= execution(ADVICE: void TraceClass.ajc$before$TraceClass$1$346234(JoinPoint)) => execution(ADVICE: void TraceClass.ajc$after$TraceClass$2$346234(JoinPoint)) => get(int TraceClass.level) <= get(int TraceClass.level) => set(int TraceClass.level) <= set(int TraceClass.level) => call(void TraceClass.offset()) => execution(void TraceClass.offset()) => get(int TraceClass.level) <= get(int TraceClass.level) <= execution(void TraceClass.offset()) <= call(void TraceClass.offset()) => get(PrintStream java.lang.System.err) <= get(PrintStream java.lang.System.err) => call(java.lang.StringBuffer(String)) <= call(java.lang.StringBuffer(String)) => call(StringBuffer java.lang.StringBuffer.append(Object)) <= call(StringBuffer java.lang.StringBuffer.append(Object)) => call(String java.lang.StringBuffer.toString()) <= call(String java.lang.StringBuffer.toString()) => call(void java.io.PrintStream.println(String)) <- execution(void WhatsGoingOn.main(String[])) <= call(void java.io.PrintStream.println(String)) <= execution(ADVICE: void TraceClass.ajc$after$TraceClass$2$346234(JoinPoint)) Fix checked in, waiting on build.
Fix available: BUILD COMPLETE - build.387 Date of build: 10/21/2004 21:05:26 Time to build: 128 minutes 30 seconds Last changed: 10/21/2004 16:41:04 Latest good AspectJ jar available at: download.eclipse.org/technology/ajdt/dev/aspectj-DEVELOPMENT.jar