4 Replies Latest reply on Jul 3, 2013 7:58 AM by adinn

    Unknown helper class executing rule in EAP

    johara

      I am trying to instrument a class in a postgres jdbc driver deployed into EAP as a module, using a custom Helper class. Whenever the rule is executed, org.jboss.byteman.rule.Rule.typeCheck can not resolve the custom Helper class, and throws the follwoing exception:

       

      org.jboss.byteman.rule.exception.TypeException: Rule.typecheck : unknown helper class ... for rule ...

       

      I have tried including the jar in the sys and boot classpath argurments, I have tried submitting the jar to an running jvm with 'bmsubmit.sh -b' but have not been able to use my Helper class in EAP 6.1.

       

      Debugging shows that the classloader (an instance of org.jboss.modules.ModuleClassLoader) can find org.jboss.byteman.rule.helper.Helper, but can not find not my rule.

       

      Has anyone seen this problem before, have I missed something?

       

      Any help resolving the issue I am experiecing would be gratefully appreciated.

       

       

      For brevity, these are simpilfied parameters/scripts that I am having an issue running;

       

      postgresInstrumentExample.btm;

       

      RULE execute query entry

      CLASS org.postgresql.core.v3.QueryExecutorImpl

      METHOD execute

       

      HELPER org.jboss.perf.InstrumentHelperExample

       

      AT ENTRY

      BIND query = $1

      IF TRUE

      DO dummyLog(Thread.currentThread().getId())

      ENDRULE

       

      org.jboss.perf.InstrumentHelperExample;

       

       

      package org.jboss.perf;

       

      import org.jboss.byteman.rule.Rule;

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


      public class InstrumentHelperExample extends Helper {


          protected InstrumentHelperExample(Rule rule) {

              super(rule);

          }

       

          public void dummyLog(long threadID){

              traceln("Started: ".concat(String.valueOf(threadID)));

          }

       

      }

       

      jvm command line options passed to EAP;

       

      JAVA_OPTS="$JAVA_OPTS -Dorg.jboss.byteman.transform.all -javaagent:${BYTEMAN_HOME}/lib/byteman.jar=listener:true,boot:${BYTEMAN_HOME}/lib/byteman.jar,sys:/tmp/byteman/postgresInstrument-1.0-SNAPSHOT.jar"

       

      contents of helper jar;

       

      $ jar tf ./target/postgresInstrument-1.0-SNAPSHOT.jar

      META-INF/

      META-INF/MANIFEST.MF

      org/

      org/jboss/

      org/jboss/perf/

      org/jboss/perf/InstrumentHelperExample.class

      org/jboss/perf/InstrumentHelper.class

      META-INF/maven/

      META-INF/maven/org.jboss.perf/

      META-INF/maven/org.jboss.perf/postgresInstrument/

      META-INF/maven/org.jboss.perf/postgresInstrument/pom.xml

      META-INF/maven/org.jboss.perf/postgresInstrument/pom.properties

       

      stack trace of error;

       

      17:38:17,416 INFO  [stdout] (JBossWeb-threads - 36) Rule.execute called for execute query entry_2

      17:38:17,418 INFO  [stdout] (JBossWeb-threads - 36) Rule.ensureTypeCheckedCompiled : error type checking rule execute query entry

      17:38:17,418 INFO  [stdout] (JBossWeb-threads - 36) org.jboss.byteman.rule.exception.TypeException: Rule.typecheck : unknown helper class org.jboss.perf.InstrumentHelperExample for rule execute query entry

      17:38:17,418 INFO  [stdout] (JBossWeb-threads - 36)     at org.jboss.byteman.rule.Rule.typeCheck(Rule.java:502)

      17:38:17,418 INFO  [stdout] (JBossWeb-threads - 36)     at org.jboss.byteman.rule.Rule.ensureTypeCheckedCompiled(Rule.java:449)

      17:38:17,418 INFO  [stdout] (JBossWeb-threads - 36)     at org.jboss.byteman.rule.Rule.execute(Rule.java:670)

      17:38:17,418 INFO  [stdout] (JBossWeb-threads - 36)     at org.jboss.byteman.rule.Rule.execute(Rule.java:651)

      17:38:17,418 INFO  [stdout] (JBossWeb-threads - 36)     at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java)

        • 1. Re: Unknown helper class executing rule in EAP
          johara

          Digging a little more into this, it appears that the classloader can only load the custom Helper class if it is packaged in org.jboss.byteman

           

          org.jboss.byteman.perf.InstrumentHelperExample - Class is found

           

          org.jboss.perf.InstrumentHelperExample - Class is not found

           

          I have also testedby pacaking the InstrumentHelperExample class into byteman.jar to eliminate the boot and sys class paths. The classloader could not find Helper classes in the updated byteman.jar where the cusotm Helper classes were not in a subpackage of org.jboss.byteman.

           

          Maybe this is a issue with org.jboss.modules.ModuleClassLoader?

          • 2. Re: Unknown helper class executing rule in EAP
            adinn

            Hi John,

             

            This problem is to do with how module loaders work in EAP, specifically JBoss Modules. This is explained in Part 1 of the Byteman tutorial and there has been some related discussion on this forum  but I'll explain the full details here for your benefit and for others.

             

            When a rule is injected into its target method all the classes it mentions are resolved via the classloader of the class which owns the target method. In an application which is using conventional class loading (i.e. no moudle loaders and the usual war, ear etc deplooyment loading scheme) that means that references to classes not defined by that loader will be pushed up the loader hierarchy, eventally reaching the system or bootstrap class loader. IN these systems class loaders are organized in a strict tree (no joins) with the boot loader above the system loader above all other loaders

             

            Actually, most loaders actually push an unresolved reference up before trying to load locally. That ensures that two war laoders will both look to their parent loader for a common class rather than each redefine their own version and end up in "classloader hell" (TM (C) Beelzebub, dat ole devil heself).

             

            If your app is using a module system then the module loaders ar enot organized in a tree. Instead they form a graph with each loader being linked to the loaders of the modules it inherits. A module loader will load classes from the packages it owns and only delegate classes in other packages to the loaders it is directly linked to. So, if your helper is in the system classpath then it will only get loaded if the delegation chain includes a loader which is willing to load the required package from the system classpath. Now in JBoss Modules your deployed ear might will be in a module loader which links to the web services, ejb etc loaders. But these loaders wil only import system packages which belong to JBoss WS, Hibernate etc. So, your helper wil nto be found.

             

            Ok, so why does your helper get found if you loacet it in the org.jboss.byteman package? Well, JBoss Modules oimplements a special get-out-of-jail-free card and EAP plays that card on behalf of Byteman automatically. Take a look at file standalone.sh (or domain.sh if you are running wiht more than one instance) in your EAP tree. If you search for org.jboss.byteman you wil see that EAP addsthe following settign to JAVA_OPTS, ensuring it gets passed on the java command line.

             

            JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=org.jboss.byteman"

             

            This tells every module loader that any class whose package starts with org.jboss.byteman should be delegated directly to the system loader. That includes sub-packages too. Without this setting injected code would not be able to refer to the Byteman error classes ParseException, TypeException and ExecuteException so Byteman would be totally broken. If you want your helper also to be visible you just need to add your helper class's package to this list using a ',' as separator

             

             

            JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=org.jboss.byteman,org.my.helpers"

             

            Try that and let me know what happens.

            • 3. Re: Unknown helper class executing rule in EAP
              johara

              Andrew,

               

              Thank you for your prompt and thorough response.

               

              I had assumed that as the module classloader of the org.postgresql.core.v3.QueryExecutorImpl class has been able to delegate to parent classloaders and load the standard Byteman helper class, then it should have been able to resolve my Helper class if I had included the jar in the system classpath. I had even tested packaging mmy customer Helper in byteman.jar, to no avail.

               

              Adding my package name to -Djboss.modules.system.pkgs (JBOSS_MODULES_SYSTEM_PKGS in standalone.conf) enables my Helper class to be loaded, and is working as exepcted.

               

              Thanks a lot for your help

               

              John

              • 4. Re: Unknown helper class executing rule in EAP
                adinn

                John O'Hara wrote:

                 

                . . .

                Adding my package name to -Djboss.modules.system.pkgs (JBOSS_MODULES_SYSTEM_PKGS in standalone.conf) enables my Helper class to be loaded, and is working as exepcted.

                 

                Thanks a lot for your help

                 

                No problem and I am glad everything is now working.

                 

                If you can share any details of precisely what you are using Byteman to do and, indeed, post  your rules and helper code I am sure others might be interested to see them (assuming,of course, that you are not limited by confidentiality restrictions). It's very helpful for other users, not to mention me and those who help me to develop Byteman, to understand different use cases. Even if you cannot disclose any details thanks for using Byteman and for reporting your problems.

                 

                regards,

                 

                 

                Andrew Dinn