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不允许访问某些方法。
任何帮助,非常感谢。
答
尝试的
cr.accept(cv, ClassReader.EXPAND_FRAMES);
代替
cr.accept(cv, 0);
异常不是从Java代理抛出,所以你不能看到则抛出。
很难相信ASM决定不调用'visitMethod',这取决于你将返回哪个方法,因为这需要预知。你如何确定该方法尚未被调用? – Holger