[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[ajdt-dev] Some @aspectj advices leading to some runtime errors
|
Hi list,
Glad to use AspectJ in one of our project!
[I use AJDT 2.2.0.e37x-20120105-1100 with AspectJ version: 1.7.0.20111215190600 in my IDE. And AspectJ 1.6.12 in my production environment]
I encounter some problems with using @aspectj.
I define the following example class in a simple AspectJ project.
<code>
package foo;
public class Test {
public final static void main(String[] args) {
Test test = new Test();
System.out.println(test.runTest());
}
public int runTest() {
return this.test(5);
}
public int test(int i) {
return i;
}
}
</code>
Then I tried different way of pointcuting the int test(int) method. I describe each time what I observe bellow.
1. Using neither args() nor this()
<code>
package foo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TestAspect {
@Pointcut("call(int foo.Test.test(int)) && "
+ " target(test)")
void testPointcut(Test test) {}
@Around("testPointcut(test)")
public Object doTest(final ProceedingJoinPoint jp,
Test test) throws Throwable {
return jp.proceed(new Object[] { test });
}
}
</code>
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at foo.Test.test_aroundBody1$advice(Test.java:18)
at foo.Test.runTest(Test.java:11)
at foo.Test.main(Test.java:7)
2. Using args() but no this()
>From reading the docs this code is correct.
<code>
package foo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TestAspect {
@Pointcut("call(int foo.Test.test(int)) && "
+ " target(test) && args(i)")
void testPointcut(Test test, int i) {}
@Around("testPointcut(test, i)")
public Object doTest(final ProceedingJoinPoint jp,
Test test, int i) throws Throwable {
return jp.proceed(new Object[] { test, i * 2 });
}
}
</code>
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to foo.Test
at foo.Test.test_aroundBody1$advice(Test.java:18)
at foo.Test.runTest(Test.java:11)
at foo.Test.main(Test.java:7)
3. Using args() and this()
<code>
package foo;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TestAspect {
@Pointcut("call(int foo.Test.test(int)) && "
+ " target(test) && args(i)")
void testPointcut(Test test, int i) {}
@Around("testPointcut(test, i) && this(t)")
public Object doTest(final ProceedingJoinPoint jp,
Test test, int i, Object t) throws Throwable {
return jp.proceed(new Object[] { t, test, i * 2 });
}
}
</code>
This version works as expected. However, it seems that the generated bytecode during weaving incorrectly builds the debug line markers as if you put a breakpoint in the advice, Eclise don't suspend inside the advice code but elsewhere in the Test class code. Also, when you try to step (in a blind way) in the code from a breakpoint in runTest(), you can observe there is somewhat a mismatch in the variable handling...
Should I raise a bug for all that ?
After playing with AspectJ source code (version 1.6.12), I suspect there might be a bug in the weaver but also in line 202 of JoinPointImpl:
state[hasThis ? 1 : 0] = adviceBindings[hasThis ? 1 : 0];
Shouldn't this be :
state[hasThis ? 1 : 0] = adviceBindings[bindThis ? 1 : 0];
Everytime you can replace the faulty proceed(..) call by a no-arg proceed() call and then this works as expected.
Thanks for you help!
Didier.aj