1 Reply Latest reply: May 3, 2013 11:07 PM by user11436730 RSS

    BytecodeInstrumentation : agent hooking seems not working.

    user11436730
      <h4>
      Requirement :
      Want to hook agent statically( as of now ) and attach the custome classfiletransformer to it so that can manipulate the byte code the object, if needed.

      Problem Statement :
      Currently premain method is getting executed and I have added the transformer instance with the instrumentation instance provided as argument in the method but still the transform() method is not getting called for the subsequent loading objects.

      Following is my code structure :
      MyObject.java - Pojo to check the bytecode instrumentation, test purpose only
      HookAgent.java - Java Agent Class
      MyClassTransformer.java - Customer Class Transformer
      MANIFEST.MF - Manifest file of the jar archive
      </h4>

      Code :
      //MyObject.java
      package com.test.object;
      
      public class MyObject {
      
           
           public String getInfo() {
                return toString();
           }
           
           @Override
           public String toString() {
                
                return "MyObject:"+hashCode();
           }
           
      }
      ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      //HookAgent.java
      package com.test;
      
      import java.lang.instrument.Instrumentation;
      
      public class HookAgent {
      
           
           private static Instrumentation _inst;
           
           public static void premain(String args,Instrumentation inst) throws Exception {
      
                System.out.println("Inside premain() : Args : " + args + ", Instrumentation : " + inst);
                _inst = inst;
                _inst.addTransformer(new MyClassTransformer());
                
                
           }
           
           public static void agentmain(String args,Instrumentation inst) {
      
                System.out.println("Inside agentmain() : Args : " + args + ", Instrumentation : " + inst);
                _inst = inst;
                _inst.addTransformer(new MyClassTransformer());
                
           }
      }
      -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      //MyClassTransformer.java
      package com.test;
      
      import java.lang.instrument.ClassFileTransformer;
      import java.lang.instrument.IllegalClassFormatException;
      import java.security.ProtectionDomain;
      
      public class MyClassTransformer implements ClassFileTransformer {
      
           
           public MyClassTransformer() {
                System.out.println("MyClassTransformer() ... starting construction...");
           }
           @Override
           public byte[] transform(ClassLoader arg0, String arg1, Class<?> arg2,
                     ProtectionDomain arg3, byte[] arg4)
                     throws IllegalClassFormatException {
      
                System.out.println("Inside transform() : ClassLoader : " + arg0 + 
                          "Arg1 : " + arg1 +
                          "Class : " + arg2.getName() +
                          "ProtectedDomain : " + arg3 + 
                          "byte : " + arg4) ;
                
                return null;
           }
      
      }
      ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      MANIFEST.MF
      Main-Class: com.test.main.MainClass
      Agent-Class: com.test.HookAgent
      Can-Redefine-Classes: true
      Can-Retransform-Classes: true
      Premain-Class: com.test.HookAgent
      ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      //MainClass.java
      package com.test.main;
      
      import com.test.object.MyObject;
      
      public class MainClass {
      
           public static void main(String[] args) {
                System.out.println("Main started....");
                System.out.println("Args : " + args.length);
                System.out.println(new MyObject().getInfo());
                System.out.println("Main completed...");
           }
           
           
      }
      ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      Current Output :
      $ java -javaagent:../myjar.jar com.test.main.MainClass test test1 test2

      Inside premain() : Args : null, Instrumentation : sun.instrument.InstrumentationImpl@7587b2
      MyClassTransformer() ... starting construction...
      Main started....
      Args : 3
      MyObject:31778523
      Main completed...


      I expected that the arguments (run time to main) would also appear in first argument of premain() method but that's not the case and also, there is no call to the transform() method that takes place when MyObject or even MainClass is loaded.

      Appreciate any help on this.
      Thanks in advance.

      Edited by: user11436730 on May 3, 2013 11:11 PM
        • 1. Re: BytecodeInstrumentation : agent hooking seems not working.
          user11436730
          <h4>
          I have found the problem and understood the behavior.

          Problem 1: The args were not received by the premain() method as received by the main() method.
          Reason : The argument is not passed implicitly to the premain() method once passed to the main method, instead the argument needs to be passed explicitly while invoking the java program. For example :

          java -javaagent:../myjar.jar=testargs com.test.main.MainClass testargs

          Problem 2 : tranform() in MyClassTranformer is not invoked for the subsequently loading classes.
          Reason : The method was getting invoked but due the sysout given the transform() method was throwing exception as classname argument was null and .getName() was invoked on that,after removing the method is getting invoked in proper flow.

          Thanks.
          </h4>