我是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不允许访问某些方法。
非常感谢任何帮助。
答案 0 :(得分:0)
尝试
cr.accept(cv, ClassReader.EXPAND_FRAMES);
而不是
cr.accept(cv, 0);
不会从java代理抛出异常,因此您无法看到抛出IllegalArgumentException。