Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ajdt-dev] Some @aspectj advices leading to some runtime errors

Hi,

I would raise AspectJ bugzillas, perhaps one for the proceed problem
and one for the line number debug information being incorrect.

Code style aspects can do more checking around the proceed() call.  If
you are using annotation style we would have to generate checking code
that ran at runtime, to avoid errors like this:

> Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1

we don't generate that code and so unless you get the right
incantation for your proceed parameters it will manifest as nasty
runtime failures. There have been several bugs in this area over the
years, it needs a big refactoring.

> Shouldn't this be :
>
> state[hasThis ? 1 : 0] = adviceBindings[bindThis ? 1 : 0];

could be.  If that fixes all your tests and doesn't break any of the
AspectJ tests, we can put it in.  If you could attach patches to the
bugzilla that would be great.  if you want I can show you how to
create AspectJ testcases that you could also contribute back to the
regression test suite.

cheers,
Andy

On 10 January 2012 03:58,  <ptitjes@xxxxxxx> wrote:
> 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
> _______________________________________________
> ajdt-dev mailing list
> ajdt-dev@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/ajdt-dev


Back to the top