Java ASM没有访问我的AdviceAdapter的所有方法

问题描述:

我是ASM和字节码工具的初学者,并试图通过一个简单示例进行学习。我想访问加载的所有类的所有方法,并将其标记为打印方法。Java ASM没有访问我的AdviceAdapter的所有方法

附加是我的程序,但它不按预期工作。每个加载的类只有几个方法被访问,其余的被忽略。似乎没有理解某些人被访问的是什么,有些人被忽略。

例如,当加载“javax/servlet/http/HttpServlet”类时,它仅针对构造函数和doGet方法调用visitMethod并忽略其余方法。

ASMAgent.java

package com.ag.asm; 

import java.lang.instrument.Instrumentation; 

public class ASMAgent { 
    public static void premain(String agentArgs, Instrumentation inst) { 
     System.out.println("Starting the agent"); 
     inst.addTransformer(new AGClassTransformer()); 
    } 
} 

AGClassTransformer.java

package com.ag.asm; 

import java.lang.instrument.ClassFileTransformer; 
import java.lang.instrument.IllegalClassFormatException; 
import java.security.ProtectionDomain; 

import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.ClassVisitor; 
import org.objectweb.asm.ClassWriter; 

public class AGClassTransformer implements ClassFileTransformer { 
    public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, 
      ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { 
     ClassReader cr = new ClassReader(classfileBuffer); 
     ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); 
     ClassVisitor cv = new AGMethodClassVisitor(cw, className); 
     cr.accept(cv, 0); 
     return cw.toByteArray(); 
    } 
} 

AGMethodClassVisitor.java

package com.ag.asm; 

import org.objectweb.asm.ClassVisitor; 
import org.objectweb.asm.ClassWriter; 
import org.objectweb.asm.MethodVisitor; 
import org.objectweb.asm.Opcodes; 

public class AGMethodClassVisitor extends ClassVisitor { 
    private String className; 

    public AGMethodClassVisitor(ClassWriter cw, String pClassName) { 
     super(Opcodes.ASM5, cw); 
     className = pClassName; 
    } 

    @Override 
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 
     cv.visit(version, access, name, signature, superName, interfaces); 
    } 

    @Override 
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 
     MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 
     if (mv != null) { 
      mv = new AGMethodAdapter(Opcodes.ASM5, mv, access, name, desc, className); 
      if (className.equalsIgnoreCase("javax/servlet/http/HttpServlet")) { 
       System.out.println("..." + className + ";" + name); 
      } 
     } 
     return mv; 
    } 

    public void visitEnd() { 
     cv.visitEnd(); 
    } 
} 

AGMethodAdapter.java

package com.ag.asm; 

import org.objectweb.asm.MethodVisitor; 
import org.objectweb.asm.Opcodes; 
import org.objectweb.asm.commons.AdviceAdapter; 

public class AGMethodAdapter extends AdviceAdapter { 

    private String className; 
    private String methodName; 
    private boolean isProtected; 

    public AGMethodAdapter(int api, MethodVisitor mv, int access, String name, String desc, String className) { 
     super(api, mv, access, name, desc); 
     this.methodName = name; 
     this.className = className; 
     this.isProtected = (access & Opcodes.ACC_PROTECTED) != 0; 
    } 

    @Override 
    protected void onMethodEnter() { 
     // mark method as entered 
    } 

    @Override 
    protected void onMethodExit(int opcode) { 
     // mark method as exited 
    } 
} 

这里需要注意的一点是,如果我从AGMethodClassVisitor.java的visitMethod中删除AGMethodAdapter.java作为自定义适配器,并且只返回从超类返回的内容,则所有工作都正常。不明白为什么AGMethodAdapter.java不允许访问某些方法。

任何帮助,非常感谢。

+0

很难相信ASM决定不调用'visitMethod',这取决于你将返回哪个方法,因为这需要预知。你如何确定该方法尚未被调用? – Holger

尝试的

cr.accept(cv, ClassReader.EXPAND_FRAMES); 

代替

cr.accept(cv, 0); 

异常不是从Java代理抛出,所以你不能看到则抛出。