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

时间:2017-08-10 10:17:35

标签: java bytecode instrumentation java-bytecode-asm

我是ASM和字节码检测的初学者,并尝试用一个简单的例子来学习。我想访问所有加载的类的所有方法,并标记/打印为访问过的方法。

附件是我的程序,但它没有按预期工作。每个加载的类只有少数方法被访问,其余被忽略。似乎并没有理解一些人被访问过,有些人被忽略了。

例如当" javax / servlet / http / HttpServlet"如果加载了类,它只调用visitMethod来构造函数和doGet方法并忽略其余的方法。

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不允许访问某些方法。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

尝试

cr.accept(cv, ClassReader.EXPAND_FRAMES);

而不是

cr.accept(cv, 0);

不会从java代理抛出异常,因此您无法看到抛出IllegalArgumentException。