5 Replies Latest reply on Feb 25, 2015 5:37 AM by Andrew Dinn

    Reload custom helper class

    Vinod Patil Newbie

      I installed byteman agent in a running JVM using provided "org.jboss.byteman.agent.install" with custom helper in agent option.
      How can i load modified helper classes (i.e. load helper jar) ? If i try run same Install.java gain it gives "attempting to load Byteman agent more than once",

      How to unload installed javaagent in running JVM ?

       

      Thanks in advence

        • 1. Re: Reload custom helper class
          Andrew Dinn Master

          Hi Vinod,

           

          How can i load modified helper classes (i.e. load helper jar) ? If i try run same Install.java gain it gives "attempting to load Byteman agent more than once",

           

          If you want your helper classes to be available you need to add the helper jar to the system or bootstrap classpath. You can do that using the bmsubmit script which you will find in the bin directory of your Byteman download.  To add your jar to the system classpath  on Linux execute

           

          $BYTEMAN_HOME/bin/bmsubmit.sh -s /path/to/helper.jar
          

           

          If instead you want the jar to be added to the bootstrap classpath (because your rules are being injected into Java runtime classes like java.lang.Thread, java.io.FileOutputStream) you use -b instead of -s.

           

          If you are running on Windows there is an equivalent script in the bin directory called bmsubmit.bat which does the same job.

           

          n.b. if you are using JBoss AS then you will need to make sure that your helper package is visible to all module loaders as explained here

          n.b.b. if you want to inject into Java runtime classes like java.lang.Thread etc you also need to pass '-b' as an option when you load the agent using bminstall.sh

          How to unload installed javaagent in running JVM ?

           

          Once you have installed a Java agent into running JVM it is not possible to uninstall it. Teh JDK does nto provide a mechanism to do that. However, if you unload all Byteman rules (execute command bmsubmit.sh - u) then the Byteman agent will uninject all your rules and even though it is still running it should have no visible effect on the performance of your application.

           

          regards,

           

           

          Andrew Dinn

          • 2. Re: Reload custom helper class
            Vinod Patil Newbie

            Hi Andrew,

             

            I installed byteman agent with bminstall.sh script and added custom helper class with

              $BYTEMAN_HOME/bin/bmsubmit.sh -b /path/to/helper.jar

            Now suppose i made changes in the custom helper class and rebuild the jar and again added to bootstrap classpath with same command

              $BYTEMAN_HOME/bin/bmsubmit.sh -b /path/to/helper.jar

            Now if I added rule to which call method from helper class in helper.jar application throws exception org.jboss.byteman.rule.exception.TypeException: "Rule.typecheck : unknown helper class for Rule"


            Thanks in advance,

            • 3. Re: Re: Reload custom helper class
              Andrew Dinn Master

              Hi Vinod,

              Now suppose i made changes in the custom helper class and rebuild the jar and again added to bootstrap classpath with same command

                $BYTEMAN_HOME/bin/bmsubmit.sh -b /path/to/helper.jar

               

              I am afraid that's almost certainly not going to work without restarting your JVM.

               

              Once jars are in the classpath they cannot be removed, replaced or updated, at least not with determinate consequences. If you change a jar after the JVM has loaded classes then the change to the jar contents cannot  retrospectively update  the definition of any classes which have already been loaded. Those classes will almost certainly have instances and redefining the class would risk making those instances inconsistent with their class. Also, since a modified jar will have classes located at different offsets the bootstrap loader will get very confused wen it tries to load new classes. EVen if ti coudl find them the new versions might be inconsistent with the old ones it has already loaded (they might call new methods not present in the old version). I don't know exactly what the loader will do if you remove/replace the jar you previously loaded but I suspect it will refuse to link any new code (lie the Byteman rule) against classes which belonged to the modified jar.

               

              Of course, if you restart your JVM then you can just install a new version of the helper library instead of the old one. If you cannnot restart or just don't want to then the only other option you have is to create a new jar, using a different name (or package) for your helper class, add this new jar to the bootstrap and then change your rules to refer to the new version of the helper class using the new name/package.

              • 4. Re: Reload custom helper class
                Vinod Patil Newbie

                Hi Andrew,

                If JVM unable to redefine the classes from new jar the what is the importance of "boolean allowRedefine" in class loader defined in

                "org.jboss.byteman.agent.Main" class in byteman ?

                 

                reagrds,

                Vinod

                • 5. Re: Re: Reload custom helper class
                  Andrew Dinn Master

                  Hi Vinod,

                   

                  If JVM unable to redefine the classes from new jar the what is the importance of "boolean allowRedefine" in class loader defined in

                  "org.jboss.byteman.agent.Main" class in byteman ?

                  Now that's a good question!

                   

                  The JVM does allows redefinition of classes but only within certain limits.

                   

                  Firstly, redefinition is only provided as a capability for Java agent programs like Byteman (or, say, JBoss AOP, Jacoco etc). There is no general mechanism to allow classloaders to step in and rewrite the class base if, say, it notices that the jars it was originally loading code from have been updated. The JVM allows agents to rewrite the bytecode for a class when it is first loaded. It also allows any agent to request a rewrite of a class after it has been loaded (the latter option explains why allowRedefine occurs in class Main). However, whenever a rewrite occurs -- either at first load or because of an agent request -- the JVM always starts with the bytecode it first obtained from disk and then allows each Java agent to modify the bytecode, one after another. If you were clever enough you could try to use this mechanism to reload different versions of classes (JRebel is one product which tries to do that). However, you need to be really clever to get it to work and it won't always work because of another limitation imposed b the JVM.

                   

                  When a class is first loaded agent programs can do whatever they like to rewrite the code. They can add or remove members, change method signatures or field types, redefine the super class, add interfaces -- so long as the change results in legal Java bytecode it is ok. However, after any initial transformations at first load all these structural elements of the class becomes fixed. If an agent requests a redefine of the class the originally loaded bytecode will be passed to each agent in turn to do whatever transformation is needed but the final bytecode must be structurally equivalent to whatever was used after the initial load + transform. The bytecode which defines the methods can be changed but that is all. So, any agent which changes structure the first time needs to guarantee to change structure every time. If an agent wants to be able to make changes which are temporary and later on be able to remove them then it cannot change structure.

                   

                  n.b. Byteman only ever rewrites method bytecode. It never modifies class structure.

                   

                  regards,

                   

                   

                  Andrew Dinn