4 Replies Latest reply on Mar 5, 2013 7:34 AM by willreichert

    VerifyError when binding thread.getId() and compileToBytecode

    willreichert

      HI All:

       

      I noticed the byteman scripts on my server were not logging when using compileToBytecode in the benchmark environment and created a local test to troubleshoot. The local environment simply logs the threadId on method entry but I see a java.lang.VerifyError whenever I try and BIND Thread.currentThread().getId() while also using compileToBytecode.  The Byteman script is the following:

       

      RULE perf.byteman.runner.RunByteman.foo_entry
      CLASS perf.byteman.runner.RunByteman
      METHOD foo
      AT ENTRY
      BIND
      threadId =   ""+Thread.currentThread().getId();
      threadName = Thread.currentThread().getName();
      IF TRUE
      DO
      openTrace("schedule","/home/wreicher/foo.stacks.log");
      traceln("schedule"," threadId="+threadId);
      ENDRULE
      

      and I am using the following JVM arguments:

       

      -javaagent:/home/wreicher/tools/byteman/byteman-download-2.1.2/lib/byteman.jar=listener:true,port:9876,script:/home/wreicher/tools/byteman/fooStack.btm,boot:/home/wreicher/tools/byteman/byteman-download-2.1.2/lib/byteman.jar
      -Dorg.jboss.byteman.transform.all
      -Dorg.jboss.byteman.compileToBytecode
      

       

      The console log from running my simple test is the following:

      Installed rule using default helper : perf.byteman.runner.RunByteman.foo_entry
      perf.byteman.runner.RunByteman.foo_entry : java.lang.VerifyError: (class: org/jboss/byteman/rule/helper/Helper_HelperAdapter_Compiled_1, method: execute0 signature: ()V) Stack size too large
      Exception in thread "main" org.jboss.byteman.rule.exception.ExecuteException: perf.byteman.runner.RunByteman.foo_entry  : caught java.lang.VerifyError: (class: org/jboss/byteman/rule/helper/Helper_HelperAdapter_Compiled_1, method: execute0 signature: ()V) Stack size too large
                at org.jboss.byteman.rule.Rule.execute(Rule.java:714)
                at org.jboss.byteman.rule.Rule.execute(Rule.java:651)
                at perf.byteman.runner.RunByteman.foo(RunByteman.java)
                at perf.byteman.runner.RunByteman.main(RunByteman.java:46)
      Caused by: java.lang.VerifyError: (class: org/jboss/byteman/rule/helper/Helper_HelperAdapter_Compiled_1, method: execute0 signature: ()V) Stack size too large
                at java.lang.Class.getDeclaredConstructors0(Native Method)
                at java.lang.Class.privateGetDeclaredConstructors(Class.java:2413)
                at java.lang.Class.getConstructor0(Class.java:2723)
                at java.lang.Class.getConstructor(Class.java:1676)
                at org.jboss.byteman.rule.Rule.execute(Rule.java:678)
                ... 3 more
      

       

      The simple same is just a main method that calls foo so I doubt there is much to be seen there but if needed I wil include it as well

       

      Please let me know if there is any other information I should be trying to collect or if you have an idea why I am seeing the VerifyError in my local test and why the benchmark test is simply not creating the log file.

       

       

      --Will

        • 1. Re: VerifyError when binding thread.getId() and compileToBytecode
          willreichert

          I started to experience the same problem with other byteman scripts and realized that the issue occurred whenever a primitive was implicitly being converted into a string. For example, I changed the BIND threadId= Thread.currentThread().getId() to BIND threadId = Long.toString(Thread.currentThread().getId()) and I no longer experience the exception and the script runs as expected. Is this the expected behavior of BIND when it comes to implicit string conversion?

          • 2. Re: VerifyError when binding thread.getId() and compileToBytecode
            adinn

            Hi Will,

             

            Thanks for reporting this and especially for pinning the problem down so precisely. It looks very much like the Byteman compiler is failing to inject the required primtive to String promotion. I will try to reproduce this today and post a fix for the next release. Expect a JIRA soon.

             

            regards,

             

             

            Andrew Dinn

            • 3. Re: VerifyError when binding thread.getId() and compileToBytecode
              adinn

              Hi Will,

               

              I have raised a JIRA for this and fixed it for release in Byteman 2.1.3 which should happen some time in the next few weeks.

               

              The problem was not specifically to do with bindings. It was actually a miscalculation of the maximum stack height attained in the bytecode generated to implement the rule body -- specifically the height around a method call. If you want the details read on

               

              Your example triggered the problem because Thread.getId() leaves the stack higher after the call then before. It pops a single stack slot containing the Thread and replaces the stack with a long which occupies two slots (n.b. these are slots in the bytecode virtual machine, not actual machine stack slots). My code was assuming the stack was always smaller after a call than before and so was not allowing for an auxiliary call which bumped the height up by one. Hence it calculated a maximum stack value which was one slot too small.

               

              Why has this not manifested before you ask (go on ask it -- ah, I'm glad you asked that). The other necessary circumstance for this to cause an error is that  the getId() call pushes the stack height to its high-water mark. Now this just happens to be the case in your example rule. So,the stack height after the getId call was 5 and   the method bytecode was generated with a stack maximum of 5. However, the auxiliary call after the call to getId() was actually pushing a 6th value -- which inconsistency the verifier detected. I have modified the stack counting code to take value pushed by the auxiliary call into account and the high-water mark for the stack is now being reported as 6.

              • 4. Re: VerifyError when binding thread.getId() and compileToBytecode
                willreichert

                Hi Andrew,

                 

                Thanks for taking a look. I'm glad to hear it was something that could be cleared up for the next build. I will stick with explicitly converting the longs to Strings for now and will go back to using longs after 2.1.3.