2 Replies Latest reply on Oct 2, 2010 10:03 AM by nwhitehead

    Constructor Execution Pointcut Causing ArrayOutOfBounds

    nwhitehead

      ==================================

      ==============Update==============

      ==================================

       

       

      I  noticed that some older beans that did not have the private ctors did  not have this problem, so I updated my newer one to use public ctors and  the issue went away. This is problematic though, and it is preferable  in this case to have them be private.

       

      My conjecture is  that this is a bug in the advisor. The synthetic ctors are introduced to  provide the advisor with access to the private natural ctors, but the resolveConstructorPointcut method does not take this into account when iterating through the array  of constructors and referencing the constructorInfos at the same array  index.

       

       

      =====================================

       

      Hello;

       

      Java 1.6

      JBoss AOP 2.1.8.GA

       

      I have been wrestling with this for a while now. I have defined a pointcut for the execution of private constructors on classes annotated with @EntityTXAttribute. However, while the weaving is going on, an ArrayOutOfBounds exception occurs, and having run it through the debugger, it seems to make sense why, but I am noit sure how to fix it.

       

      The pointcut expression is:

       

      execution(public !static * @entitypojo.annotations.EntityTXAttribute->*(..))

      OR execution(protected !static * @entitypojo.annotations.EntityTXAttribute->*(..))

      OR execution(private @entitypojo.annotations.EntityTXAttribute->new(..))


      or all public non-static methods in annotated classes, and all private constructors.

      The method invocation interceptions work perfectly, btw.

       

      My bean has 2 ctors, on parameterized and one not. I set a debugger break point on org.jboss.aop.Advisor line 1870 where the error occurs.

      What I see is this:

       

      The instance has an array called constructors which has 4 constructors in it, 2 of which I defined and 2 of which appear to be synthetic. They broadly look like this:

       

      1. private Bean()   (mine)
      2. Bean(javassist.runtime.Inner)   (synthetic)
      3. private Bean(String, String)     (mine)
      4. Bean(String, String, javassist.runtime.Inner)   (synthetic)

       

      However, the array of constructorInfos only has 2 entries in it which are

       

      1. private Bean()   (mine)
      2. private Bean(String, String)     (mine)

       

       

      The method code looks like this:


      protected void resolveConstructorPointcut(AdviceBinding binding)
         {
            for (int i = 0; i < constructors.length; i++)
            {
               Constructor<?> constructor = constructors[i];
               if (binding.getPointcut().matchesExecution(this, constructor))
               {
                  if (AspectManager.verbose) logger.debug("constructor matched binding: " + constructor);
                  adviceBindings.add(binding);
                  binding.addAdvisor(this);

                 // this is where the error occurs. Line 1870.
                  pointcutResolved(constructorInfos[i], binding, new ConstructorJoinpoint(constructor));
                  // if we must keep track of deprecated fields and the field is already initialized
                  if (AspectManager.maintainAdvisorMethodInterceptors && constructorInterceptors != null)
                  {
                     constructorInterceptors[i] = constructorInfos[i].getInterceptors();
                  }
               }
            }
         }

       

      This code assumes the number of constructorInfos is at least the same as the number of constructors, but since it is not, it throws an array out of bounds exception.

       

      Am I doing something wrong here, or is it a bug ?

       

      Much appreciated.

       

      //Nicholas

        • 1. Re: Constructor Execution Pointcut Causing ArrayOutOfBounds
          kabirkhan

          Is Bean an inner class?

           

          Unfortunately nobody is working actively on JBoss AOP at the moment but you seem very capable, so if you create a patch and a test we can make sure it gets included in the upstream code. If you're interested let me know and I can help with getting you set up.

          • 2. Re: Constructor Execution Pointcut Causing ArrayOutOfBounds
            nwhitehead

            Hello Kabir;

             

            Thanks for the response.

             

            I hope the fact that no one is working on JBoss AOP right now is because it is complete and stable. Not being deprecated is it ?

             

            After some more investigation and some simplified test cases, I have determined that the issue arises in this specific set of conditions:

             

            1. An execution pointcut on private constructors.
            2. An advised class that has a private parameterless constructor and one or more parameterized private constructors.

             

            If the constructors are not private, or there is only a single private parameterless constructor, the error does not occur.

             

            There are probably a number of other combinations of conditions, but I believe my patch should work for all for them and not break anything.

             

            The issue is on line 1870 of org.jboss.aop.Advisor in JBoss AOP 2.1.8 GA. The line of code is:

             

            pointcutResolved(constructorInfos[i], binding, new ConstructorJoinpoint(constructor));

             

            My patch, which is very simplistic, replaces this line with:

             

            for(ConstructorInfo ci: constructorInfos) {
               if(constructor.equals(ci.getConstructor())) {
                  pointcutResolved(ci, binding, new ConstructorJoinpoint(constructor));
                  break;
               }
               throw new NotImplementedException(

                    "Failed to match ConstructorInfo for Constructor [" + constructor.toGenericString() + "]");
            }

             

            The premise is that in this condition, the array of Constructors is not the same size as the array of ConstructorInfos, so we cannot use a simple index reference. Iterating through the available ConstructorInfos find the matching one and then executes the pointcutResolved normally. Not sure if the thrown exception is JBoss compliant, but I am also not sure if it will realistically ever reach that line anyways.

             

            At any rate, let me know what I can do to submit this patch if you need something more formal.

             

            Cheers.

             

            //Nicholas