4 Replies Latest reply on Oct 9, 2006 7:44 PM by stalep

    Is there a static vs. dynamic binding problem with jboss aop

    manu4ever

      Further to my question below, here's another example where something really seriously screwy is happening. The basic infrastructure comes from the docs/aspect-framework/examples/annotation example, but some of the files are modified and there is one new file:

      Driver.java
      =======

      public class Driver {
      public static void main(String[] args) {
      SUBPOJO spojo = new SUBPOJO(2);
      spojo.someMethod();
      }
      }

      POJO.java
      =======

      public class POJO {
      @trace int field;

      public POJO() {
      }

      public POJO(int i) {
      field = i;
      }

      @billable public void someMethod() {
      System.out.println("someMethod");
      System.out.println("FIELD = " + field);
      }
      }


      SUBPOJO.java
      =========

      public class SUBPOJO extends POJO {
      private int field;
      public SUBPOJO() {
      }

      public SUBPOJO(int i) {
      super(i/2);
      field = i;
      }

      public void someMethod() {
      System.out.println("ENTERING SUBPOJO:someMethod");
      super.someMethod();
      System.out.println("LEAVING SUBPOJO:someMethod");
      }
      }

      Here is the jboss-aop.xml file:

      <?xml version="1.0" encoding="UTF-8"?>
      <aop>
       <bind pointcut="execution(POJO->@billable(..))">
       <interceptor class="BillingInterceptor"/>
       </bind>
       <bind pointcut="execution(* POJO->@billable(..))">
       <interceptor class="BillingInterceptor"/>
       </bind>
       <bind pointcut="all(@trace)">
       <interceptor class="TraceInterceptor"/>
       </bind>
      </aop>


      If I remove the "@trace" from the definition of field "field" in POJO.java then this works almost as expected:

      run:
      [java] ENTERING SUBPOJO:someMethod
      [java] billing...[advisedMethod=public void POJO.someMethod(), unadvisedMethod=public void POJO.POJO$someMethod$aop(), metadata=null, targetObject=SUBPOJO@a4e743, arguments=null]
      [java] someMethod
      [java] FIELD = 1
      [java] LEAVING SUBPOJO:someMethod

      FIELD is correctly displayed as 1 (the value of POJO.field). I say "almost" because I don't expect "billable" to be applied but suspect there's some means of making that happen.

      However if I put back the "@trace" in the definition of "field" in POJO.java then this is what happens:

      run:
      [java] <<< Trace : write field name: int POJO.field
      [java] >>> Leaving Trace
      [java] <<< Trace : write field name: int POJO.field
      [java] >>> Leaving Trace
      [java] ENTERING SUBPOJO:someMethod
      [java] billing...[advisedMethod=public void POJO.someMethod(), unadvisedMethod=public void POJO.POJO$someMethod$aop(), metadata=null, targetObject=SUBPOJO@1112783, arguments=null]
      [java] someMethod
      [java] <<< Trace : read field name: int POJO.field
      [java] >>> Leaving Trace
      [java] FIELD = 2
      [java] LEAVING SUBPOJO:someMethod


      Now the value read for field is WRONG. It is reading SUBPOJO.field rather than POJO.field. This appears to be because of the way that jboss aop rewrites the accessor method, switching from static to dynamic binding.

      Even more oddly, if I change jboss-aop.xml to look like this:

      <?xml version="1.0" encoding="UTF-8"?>
      <aop>
       <bind pointcut="call(POJO->@billable(..))">
       <interceptor class="BillingInterceptor"/>
       </bind>
       <bind pointcut="call(* POJO->@billable(..))">
       <interceptor class="BillingInterceptor"/>
       </bind>
       <bind pointcut="all(@trace)">
       <interceptor class="TraceInterceptor"/>
       </bind>
      </aop>



      Then this is what happens:


      run:
      [java] <<< Trace : write field name: int POJO.field
      [java] >>> Leaving Trace
      [java] <<< Trace : write field name: int POJO.field
      [java] >>> Leaving Trace
      [java] ENTERING SUBPOJO:someMethod
      [java] billing...SUBPOJO_1_MByMInvocation@1989f84
      [java] ENTERING SUBPOJO:someMethod
      [java] billing...SUBPOJO_1_MByMInvocation@110c424
      [java] ENTERING SUBPOJO:someMethod
      [java] billing...SUBPOJO_1_MByMInvocation@1bd2664
      [java] ENTERING SUBPOJO:someMethod
      [java] billing...SUBPOJO_1_MByMInvocation@1238bd2
      [java] ENTERING SUBPOJO:someMethod
      [java] billing...SUBPOJO_1_MByMInvocation@b0bad7
      etc etc....

      Ad infinitum, or at least until there is a stack overflow. This also appears to be down to a code rewrite that replaces static binding with dynamic binding.

      Is there some configuration mechanism to avoid these errors - which are about as fundamental as I can imagine - or do I switch to aspectj which seems to get this right?



        • 1. Re: Is there a static vs. dynamic binding problem with jboss
          manu4ever

          Actually I was wrong to say that it was reading SUBPOJO.field. It's actually reading POJO.field. The problem is that when I try to write to SUBPOJO.field, the code is rewritten by jboss AOP in such a way that it writes to POJO.field instead.

          The problem seems to be the mechanism used to intercept field accesses. Static methods for read and write accesses to POJO.field are added to POJO. However in SUBPOJO, the same static methods in POJO are used again when attempting to access SUBPOJO.field.

          So in the example above, what is actually happening is that the constructor for SUBPOJO is correctly calling POJO's constructor with an arg of 1, but is then calling POJO.field_r_$aop() or whatever it's called, in the misguided belief that this will set SUBPOJO.field, or that the two are the same which they obviously aren't.

          Comments?

          • 2. Re: Is there a static vs. dynamic binding problem with jboss
            kabirkhan

            This seems like a bug, I am currently busy trying to get AOP 2.0 alpha ready, but will try to get this in before then.

            http://jira.jboss.com/jira/browse/JBAOP-284

            • 3. Re: Is there a static vs. dynamic binding problem with jboss
              stalep

              hi, a simple workaround for the fieldproblem is to either to rename the field variable so that it doesnt match the field of the subclass or make the field variable private accessible. the only workaround for the overflow/loop problem is to rename one of the methods calling. i'll make a post when a fix has been commited to the repository.

              • 4. Re: Is there a static vs. dynamic binding problem with jboss
                stalep

                this problem is now fixed, it was a bug in javassist. the fix is atm only available from the javassist cvs repository, but the upcoming jboss-aop 2.0 will include this fix.