2015-03-02 14 views
1

所以,用下面的代碼寫的,我的輸出是:Java字節碼儀器儀表,MethodVisitor中爲空

Starting application with the Agent 
Visiting class: HelloWorld 
Class Major Version: 51 
Super class: java/lang/Object 
Source: HelloWorld.java 
Method: <init> desc =()V cv = [email protected] and mv = null 
Method: main desc = ([Ljava/lang/String;)V cv = [email protected] and mv = null 
Method: foo desc =()V cv = [email protected] and mv = null 
Method ends here 
Done instrumenting: HelloWorld 

這是我百思不得其解。爲什麼我的methodVisitornull?當classVisitornull時,ASM源代碼似乎只返回nullmethodVisitor,這在我的情況中不是這樣。

package com.amir.agent.instrumentor; 

import org.objectweb.asm.AnnotationVisitor; 
import org.objectweb.asm.Attribute; 
import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.ClassVisitor; 
import org.objectweb.asm.FieldVisitor; 
import org.objectweb.asm.MethodVisitor; 
import org.objectweb.asm.Opcodes; 

public class amirClassVisitor { 

    private byte[] outData = null; 

    public amirClassVisitor() { 
    } 

    public void performInstrumentation(final String className, 
             final byte[] classAsBytes) { 
     final ClassVisitor cl = new ClassVisitor(Opcodes.ASM4) { 
      @Override 
      public void visit(final int version, 
           final int access, 
           final String name, 
           final String signature, 
           final String superName, 
           final String[] interfaces) { 
       System.out.println("Visiting class: "+name); 
       System.out.println("Class Major Version: "+version); 
       System.out.println("Super class: " + superName); 
       super.visit(version, access, name, signature, superName, interfaces); 
      } 

      @Override 
      public void visitOuterClass(final String owner, 
             final String name, 
             final String desc) { 
       System.out.println("Outer class: "+owner); 
       super.visitOuterClass(owner, name, desc); 
      } 

      @Override 
      public AnnotationVisitor visitAnnotation(final String desc, 
                final boolean visible) { 
       System.out.println("Annotation: "+desc); 
       return super.visitAnnotation(desc, visible); 
      } 

      @Override 
      public void visitAttribute(final Attribute attr) { 
       System.out.println("Class Attribute: " + attr.type); 
       super.visitAttribute(attr); 
      } 

      @Override 
      public void visitInnerClass(final String name, 
             final String outerName, 
             final String innerName, 
             final int access) { 
       System.out.println("Inner Class: " + innerName + " defined in " + outerName); 
       super.visitInnerClass(name, outerName, innerName, access); 
      } 

      @Override 
      public FieldVisitor visitField(final int access, 
              final String name, 
              final String desc, 
              final String signature, 
              final Object value) { 
       System.out.println("Field: "+name+" "+desc+" value:"+value); 
       return super.visitField(access, name, desc, signature, value); 
      } 

      @Override 
      public void visitEnd() { 
       System.out.println("Method ends here"); 
       super.visitEnd(); 
      } 

      @Override 
      public MethodVisitor visitMethod(final int access, 
              final String name, 
              final String desc, 
              final String signature, 
              final String[] exceptions) { 
       final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 
       System.out.println("Method: " +name+ " desc = " +desc+ " cv = " +this+ " and mv = " +mv); 
       return mv; 
      } 

      @Override 
      public void visitSource(final String source, 
            final String debug) { 
       System.out.println("Source: "+source); 
       super.visitSource(source, debug); 
      } 

     }; 

     final ClassReader classReader = new ClassReader(classAsBytes); 
     classReader.accept(cl, 0); 
     System.out.println("Done instrumenting: " +className); 

    } 

    public byte[] result() { 
     return outData; 
    } 

} 

編輯:

我把這個代碼:

public class ClassLoadInterceptor implements ClassFileTransformer { 

    @SuppressWarnings("unchecked") 
    public byte[] transform(final java.lang.ClassLoader loader, 
          final java.lang.String className, 
          final java.lang.Class classBeingRedefined, 
          final java.security.ProtectionDomain protectionDomain, 
          final byte[] classfileBuffer) throws IllegalClassFormatException { 

     if (!(className.startsWith("java") || className.startsWith("sun") || className.startsWith("com/workday/agent"))) { 
      WorkdayClassVisitor v = new WorkdayClassVisitor(); 
      v.performInstrumentation(className, classfileBuffer); 
      System.out.println("\t Instrumenting : " +className); 
      byte[] instrumented_class = v.result(); 
      writeOutClassFile("debug", className + ".class", classfileBuffer); 
      writeOutClassFile("debug", className + "_instrumented" + ".class", instrumented_class); 
      return instrumented_class; 
     } 

     return classfileBuffer; 

    } 
+0

你怎麼稱呼這個方法? – 2015-03-02 23:19:47

回答

1

你打印出來的不是「我的methodVisitor」,但是受super調用的visitMethod返回,其他價值字由默認值返回ClassVisitor.visitMethod

返回
一個對象訪問該方法的字節碼,或null如果這個類的訪問者不想訪問此方法的代碼。

由於抽象類ClassVisitor不執行任何操作,它在訪問的方法沒有什麼興趣,因此null是完美的返回值。

因此,您需要實例化一個新的MethodVisitor來實現您想要的行爲。或者,由於您似乎打算安排課程,請讓您的課程訪問者轉到ClassWriter,然後您將其傳遞給super class constructor。這樣您將繼承可以自定義的複製行爲。然後,super.visitMethod將返回一個非null方法訪問者,它將複製該方法。

+0

謝謝你的回答。爲了確認你所說的話,我創建了一個新的MethodVisitor,它似乎完全符合你的意思。我仍然不明白的是ClassWriter的角色。你能證明如何適合我粘貼在上面的代碼? – 2015-03-03 18:58:36