1 Reply Latest reply: Jul 7, 2009 1:44 PM by 843798 RSS

    Native method instrumentation using ClassFileTransformer

    843798
      Hello all,

      I am trying to instrument a native method during its class loading. Quoting parts of http://www.j2ee.me/javase/6/docs/api/java/lang/instrument/Instrumentation.html#setNativeMethodPrefix(java.lang.instrument.ClassFileTransformer,%20java.lang.String):

      "When used with the ClassFileTransformer, [the setNativeMethodPrefix method] enables native methods to be instrumented."

      I have used the ClassFileTransformer class with ASM in the past, but this time I don't think this can be done in the same way: native methods cannot be bytecode-instrumented - they should be wrapped within a non-native method, that would then use the setNativeMethodPrefix to correctly resolve the calls to the native method.

      However, how am I supposed to wrap a native method with a non-native one with ClassFileTransformer? Is the required code part of the transform method? Should it be within the ClassAdaptor and if so, how? A simple example in code of how (and where) you would wrap the foo method described in the link above or any link that I might have missed during my search, would be really appreciated.

      Thanks for your taking some time to help me

      Best Regards,
      John

      Edited by: Johnny83 on Jul 6, 2009 11:11 AM
        • 1. Re: Native method instrumentation using ClassFileTransformer
          843798
          Ok, I did what I wanted to. ASM was used again to wrap the native methods in my ClassAdapter inherited class, and then bytecode-instrument the wrapper function in a class NativeMethodAdapter (which I ommit here, since each user may select any different instrumentation for the wrapper method). The example I would be looking for would be along the lines of:
          public class MyClassAdapter extends ClassAdapter {
          
              private String className;
              ClassWriter myVisitor;
          
              public MyClassAdapter(ClassVisitor arg0) {
                   super(arg0);
                  myVisitor = (ClassWriter)arg0;
              }
              
              @Override
              public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
                  this.className = name;
                  cv.visit(version, access, name, signature, superName, interfaces);  
              }
          
              @Override
              public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
          
                  boolean isNative = (access & ACC_NATIVE) != 0;
                  if (isNative) {
                       
                       // Create the wrapper method with the same credentials, except from being native
                       myVisitor.newMethod(className, name, desc, false);
                       MethodVisitor mv = myVisitor.visitMethod(access ^ ACC_NATIVE, name, desc, signature, exceptions);
                       mv = new NativeMethodAdapter(mv, className, name, desc);
                       
                       // Create the prefixed method that will be linked to the actual implementation of the original method
                          // the usage of setNativeMethodPrefix elsewhere is assumed here
                       myVisitor.visitMethod(access, "__wrapper_prefix_" + name, desc, signature, exceptions);
                       return mv;
                  } else {
                         return myVisitor.visitMethod(access, name, desc, signature, exceptions);
                 }
                  
          
              }
          
          }
          Note: the above provided code has not been tested - it is meant to provide an indication of how to proceed with similar problems.

          Hope this helps,
          Johnny

          Edited by: Johnny83 on Jul 7, 2009 11:41 AM

          Edited by: Johnny83 on Jul 7, 2009 11:42 AM

          Edited by: Johnny83 on Jul 7, 2009 11:44 AM