5 Replies Latest reply on Aug 3, 2012 11:28 AM by Jaromir Hamala

    Use of generics in helper class methods

    Andy Overton Newbie

      Hi,

       

      I am new to using Byteman and have come across an issue that I can't seem to resolve and can't find any information on.

       

      I've cut out any extra code and just put in the code i'm having difficulty with to make it easier to follow.

       

      I have a main class as follows :

       

      class AppMain

      {

           public static void main(String[] args)

           {

                                  String[] testArray = {"One", "Two", "Three"};

           }

      }

       

      I then have a helper class as follows :

       

      import org.jboss.byteman.rule.Rule;

      import org.jboss.byteman.rule.helper.Helper;

       

       

      public class MyHelper extends Helper

      {

                protected MyHelper(Rule rule)

                {

                               super(rule);

        }

       

                public <E> void displayArray(E[] inputArray)

                {          

                               for (E element : inputArray)

                               {       

                                              System.out.printf("%s ", element);

                               }

       

                               System.out.println();

                }

       

       

                public void displayArray2(String[] strings)

                {

                               for (String s : strings)

                               {

                                              System.out.println("S = " + s);

                               }

                }

      }

       

      Now, what I want to do is to call the displayArray method passing in the String array created in Main and have it display the contents.

       

      My rule is as follows :

       

      RULE MY TEST RULE

      CLASS AppMain

      METHOD main

      HELPER MyHelper

      AT EXIT

      IF true

      DO displayArray($testArray);

      ENDRULE

       

      If I call displayArray2 then it works fine. However, if I call displayArray which uses generics then I get the following error:

       

      Rule.execute called for MY TEST RULE_1

      Rule.ensureTypeCheckedCompiled : error type checking rule MY TEST RULE

      org.jboss.byteman.rule.exception.TypeException: DollarExpression.typeCheck : invalid expected type java.lang.Object[] for bound parameter $testArray file appmain.btm line 16

              at org.jboss.byteman.rule.expression.DollarExpression.typeCheck(DollarExpression.java:172)

              at org.jboss.byteman.rule.expression.MethodExpression.findMethod(MethodExpression.java:245)

              at org.jboss.byteman.rule.expression.MethodExpression.typeCheck(MethodExpression.java:172)

              at org.jboss.byteman.rule.Action.typeCheck(Action.java:106)

              at org.jboss.byteman.rule.Rule.typeCheck(Rule.java:523)

              at org.jboss.byteman.rule.Rule.ensureTypeCheckedCompiled(Rule.java:449)

              at org.jboss.byteman.rule.Rule.execute(Rule.java:670)

              at org.jboss.byteman.rule.Rule.execute(Rule.java:651)

              at AppMain.main(AppMain.java:8)

       

       

      Is it possible to call a method which has a generic parameter? Or can someone point me in the direction of more information on this as I can't find any anywhere.

       

      Thanks in advance,

       

      Andy

        • 1. Re: Use of generics in helper class methods
          Andrew Dinn Master

          Hi Andy,

           

          Andy Overton wrote:

           

          . . .

           

          Is it possible to call a method which has a generic parameter? Or can someone point me in the direction of more information on this as I can't find any anywhere.

           

          At the moment Byteman's type checker does not understand generics -- not at all. So, although it is possible to call a method with generic signatures Byteman will type check the call using the erased signaure and this means that there are situations where the type checker will reject valid calls. This problem arises with your example because you are passing a String[] and the method you are calling has an Object[] in its erased signature. You can pass a String where an Object is needed but you cannot pass a String[] in place of an Object[].

           

          Adding awareness of generics to the type checker is something I have thought about for a while but, hmm ... let's just say it presents some interesting challeges :-). It's maybe not too difficult dealing with situations like the one you present where the rule body simply uses an instance of a generic type or calls a generic method -- in these cases given enough  surrounding type information it should be possible to detect incorrect usage as well as reject usage where not enough information is available to identify the types involved while still allowing most correct usage to proceed. Although, I'll just qualify that by noting that type-checking normal Java generics is a slippery slope -- there are many  examples of type-correct generic code which javac fails to accept. When you add the fact that Byteman tries to avoid you having to write type declarations by inferring types this makes the problem of type checking its rules a lot harder than type checking for normal Java generic code.

           

          The harder problem is defining some way for rules which are injected into generic code to use the generic information in the signature of the target method. That essentially means that the rules themselves become type-parameterised and the type checker has to be able to operate on both types and type variables. I'm still thinking about this problem which is why I have not done anything at all yet. So, apologies for the current limitations and if you know any type theorists out there with a few spare cycles . . . :-)

          • 2. Re: Use of generics in helper class methods
            Andy Overton Newbie

            Hi Andrew,

             

            Thanks for the super fast response, stops me spending all afternoon trying to work it out. Much appreciated!

             

            I kind of figured that would be the case but thought it was worth asking just in case I was doing something wrong.

             

            Many thanks,

             

            Keep up the good work!

             

            Andy

            • 3. Re: Use of generics in helper class methods
              Jaromir Hamala Newbie

              Hi Andrew,

              I'm sorry for re-opening an aswered topic, but what do you mean by:

              This problem arises with your example because you are passing a String[] and the method you are calling has an Object[] in its erased signature. You can pass a String where an Object is needed but you cannot pass a String[] in place of an Object[].

              Arrays is Java are covariant, so it should be possible.

               

              public void acceptAnyArray(Object[] array) { [..] }

               

              String[] arrString = {"One", "Two", "Three"};

              acceptAnyArray(arrString); //still valid Java

               

               

              Sure, you are risking a runtime exception if you try to insert instance of Object into such array. But it should be perfectly safe for reading.

              Am I missing something?

               

              PS: Thank you for working on Byteman, it looks great!

              • 4. Re: Use of generics in helper class methods
                Andrew Dinn Master

                Hi Jaromir,

                Jaromir Hamala wrote:

                . . .

                Sure, you are risking a runtime exception if you try to insert instance of Object into such array. But it should be perfectly safe for reading.

                Am I missing something?

                Err, no not at all. You are correct that Java treats array parameters covariantly i.e. it allows you to pass a value of type B[] in place of an argument of type A[] when B <is a subtype of A. But Byteman's type checker does not allow this.

                 

                Maybe it ought to. I don't much like the idea but I guess it could be implemented fairly easily. If you think it would eb a useful feature then  raise a JIRA  and I'll stick it on the todo list. If you want to be really adventurous you could try fixing it yourself. It probably only requires some minor fiddling with the typecheck methods (probably :-).

                Jaromir Hamala wrote:


                PS: Thank you for working on Byteman, it looks great!

                Thank you. Give it a try and see if you still like it. Also, come back with any war stories -- it's always good to hear what people manage to do (or fail to do) with Byteman.

                 

                regards,

                 

                 

                Andrew Dinn

                • 5. Re: Use of generics in helper class methods
                  Jaromir Hamala Newbie

                  Hi Andrew,

                   

                  thank you for your answer. I'll try to write a patch myself.

                  I suppose the best way how to learn a tool is start hacking it

                   

                  Cheers,

                  Jaromir