2015-03-02 65 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