2 Replies Latest reply on Oct 12, 2012 3:49 AM by whitingjr

    Unexpected exception transforming using bmcheck

    whitingjr

      Hi,

      I am using Byteman to expose counters for particular events in the system my team is using.

       

      I have found the execution of the JMXHelper to work successfully to expose the counter on transformed bytecode.

       

      But when I use the bmcheck.sh script Byteman is reporting an error. So I have a situation where a working script in the JVM is throwing this error message. Which is unexpected.

       

      $ ~/java/jboss/byteman/byteman-download-2.1.0/bin/bmcheck.sh -cp ~/java/projects/sample-byteman-bmcheck-issue/src/main/java -cp ~/java/jboss/byteman/byteman-download-2.1.0/sample/lib/byteman-sample.jar ~/java/projects/sample-byteman-bmcheck-issue/src/main/resources/CountTheHello.btm

      checking rule Connection timed key info against class org.jboss.byteman.sample.helper.JMXHelper

      ERROR : Unexpected exception transforming class org.jboss.byteman.sample.helper.JMXHelper using  rule "Connection timed key info" loaded from /home/whitingjr/java/projects/sample-byteman-bmcheck-issue/src/main/resources/CountTheHello.btm line 10

      java.lang.NullPointerException

       

      checking rule count the number of hello against class org.jboss.perf.HelloJBossWorld

      parsed rule "count the number of hello" for class org.jboss.perf.HelloJBossWorld

      type checked rule "count the number of cheers"

       

      TestScript: 1 total errors

                  0 total warnings

                  0 parse errors

                  0 type errors

                  0 type warnings

      $

       

       

      This is my btm script.

       

      ########################################################################

      #

      # Rule to count the cheers

      #

      HELPER org.jboss.byteman.sample.helper.JMXHelper

       

      RULE Connection timed key info

      CLASS org.jboss.byteman.sample.helper.JMXHelper

      METHOD keyInfo()

      BIND keyInfo : KeyInfo = new KeyInfo("Statistics in a Dynamic MBean")

      IF TRUE

      DO

         keyInfo.addKey("cheers counter", KeyInfo.KEY_TYPE_CUMULATIVE, "cheers counter");

      RETURN keyInfo

      ENDRULE

       

      RULE count the number of hello

      CLASS org.jboss.perf.HelloJBossWorld

      METHOD main

      AT ENTRY

      IF TRUE

      DO

         incrementCounter("cheers counter")

      ENDRULE

       

       

      and this is my class

       

      package org.jboss.perf;

       

      public class HelloJBossWorld

      {

         public static void main(String args[])

         {

            System.out.println("Three cheers for Byteman.");

         }

      }

       

      The class is a noddy class on which to run the bmcheck.sh script.

       

       

      Is this supposed to happen with the bmcheck.sh script ?

       

      Regards,

      Jeremy

        • 1. Re: Unexpected exception transforming using bmcheck
          adinn

          Hi Jeremy,

           

          Thanks for spotting and reporting this. It is a regression introduced by the fix for BYTEMAN-211. See BYTEMAN-222 for the JIRA and associated code changes. This will be included in the next release (2.1.1). Details of the problem follow:

           

          The fix for BYTEMAN-211 modified a routine which occasionally gets called during code transformation to determine the lowest common superclass for two candidates classes A and B. It used to just lie and report Object but now that the JDK7 code verifier is checking method calls more closely it needs to really compute the correct type (e.g. if A == InterruptedException and B == IOException then it must return Exception). The tricky bit is that it must do this without loading any classes -- that's a nono in the middle of transformation.

           

          So, the java agent uses the Instrumentation instance passed at startup to check the code base for an existing loaded class with the correct name and classloader. It can then uses reflection to work its way up the superchain. If that fails it tries to load .class files from the load path as a resource and parse the bytecode to find the super and so on until it reaches a common parent.

           

          The problem arises because the offline parser does not actually register a java agent -- it just transforms class bytecode directly. So when the transformer class which tweaks the bytecode is created it gets passed null instead of an instrumentation instance. This is normally fine because it never normally tries to install any classes into the runtime. However, if it ever gets asked to look for a parent class  . . . well you can see where the problem lies.

           

          The solution is to modify the class lookup code so that it detects when inst is null and if so just resorts to the fallback of trying to load a .class file as a resource. This allows the offline checker to work ok for your example and should be ok for all other code too.

          • 2. Re: Unexpected exception transforming using bmcheck
            whitingjr

            Hi Andrew,

            Thank you for the reference to the JIRA that exists for this issue and the explanation. Looking forward to the 2.1.1 release. For now I will build from source till the next distribution is out.

             

            Regards,

            Jeremy