3 Replies Latest reply on Dec 21, 2012 11:05 AM by msulliv1

    getting java.lang.VerifyError once I set a local variable in hibernate

    msulliv1

      Hi,

      This is my first attempt at setting a local variable in hibernate/JBoss EAP 5.1.0 code and I'm struggling with trying to figure out why I'm getting a java.lang.VerifyError. The purpose of the rule is to override the @Table(name= annotation in hibernate to refer to another table at runtime.

      Based upon this thread discussion directions

      https://community.jboss.org/thread/215034

      I'm doing this on a Solaris 10 box. On windows I get a different error for a class cast exceptiion.

      I'm using byteman 2.1.2.

      I decompiled the class and looking at it I'm not sure what to look at beyond the signature, which seems to be correct.

      I'll attach a zip file with:

      a) AnnotationBinder_snippet.txt - has link to relevant source location and lines of code I believe byteman should be modifying

      b) rule_table_binding.txt - rule

      c) verify_error.txt - this is the output from server.log at system startup where the rule is triggered

      d) AnnotationBinder_javap.txt - this is the output of javap for the AnnotationBinder class

       

      Any help would be appreciated.

      Mike

        • 1. Re: getting java.lang.VerifyError once I set a local variable in hibernate
          msulliv1

          Sorry I meant to say I used the reference to thread/215034 to follow some of the instructions there in decompiling the code to look for possible answers to why the code is getting java.lang.VerifyError.

          • 2. Re: getting java.lang.VerifyError once I set a local variable in hibernate
            adinn

            Hi Mike,

             

            Thanks for posting this error and all the supporting information needed to diagnose it.

             

            I think there something  wrong in the generation of the injected code. Here is what gets injected into method bindClass:

             

               333:  astore  9

               335:  ldc_w  #457;        //String bind to table persistence binding_0

               338:  aconst_null

               339:  iconst_1

               340:  anewarray  #4;      //class java/lang/Object

               343:  dup_x2

               344:  dup

               345:  iconst_0

               346:  aload  9

               348:  aastore

               349:  invokestatic  #463; //Method org/jboss/byteman/rule/Rule.execute:(Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)V

               352:  iconst_0

               353:  aaload

               354:  checkcast  #2;      //class org/hibernate/cfg/AnnotationBinder

               357:  astore  9

               359:  aload  15

               361:  invokeinterface  #470,  1; //InterfaceMethod javax/persistence/Table.schema:()Ljava/lang/String;

             

            Line 333 is the write to table (local var slot 9) which is a String. Line 359 is the subsequent fetch of the schema from tabAnn (local var slot 15). The injected code lies between these two instructions, just after table is written. Lines 335 to 340 stack the rule key "bind to table persistence binding_0", a null target for the method call (which means bindClass must be a static method) and an args array containing all locals/parameters referenced in the rule. In this case the args array will only contain one value, the String table in slot 9. Lines 339/40 create the array with size 1 sitting above the key and null value.

             

            Line 343 duplicates the args array below the key and null value -- this copy is used later to update the local variable -- leaving the original array on top. So, we have on the stack [ ... args:Object[], key:String, null:Object, args:Object[] ]. Lines 344 to 348 copy the array at the top of the stack and then install the table name into it at offset 0 -- n.b. the aastore pops the copy of the array, leaving the stack as before with the previous 4 values.

             

            The invokestatic at line 349 enters the rule engine, running the rule and popping the top 3 arguments so that at return the stack only contains the args array.

             

            Lines 352/3 access element 0 of the array. This is because the rule engine uses the array passed in by the client to return updated values for any variables written by the rule. So, these two lines reads the new String value for table out of the object array at offset 0. Before this can be installed inlocal var slot 9 it must be cast to a String -- remember the args array is an Object[]. Instead it is being cast to an AnnotationBinder. I believe this is what causes the verify error.

             

            I am not yet sure what is going wrong but clearly the problem is that the code which plants the checkcast is misidentifying the type of the value in slot 0 of the array.

             

            I am afraid I am on holiday at the moment so I will not be able to look at this in more detail until early January. However I would like to thank you very much for providing me with this example and all the relevant information needed to identify where the problem lies. I'll reply again in the new year when I find out more about this.

             

            regards,

             

             

            Andrew Dinn


            • 3. Re: getting java.lang.VerifyError once I set a local variable in hibernate
              msulliv1

              Thanks Andrew. The issue is not pressing. It can wait. Have a good holiday!