背景
我想使用Java框架ASM对一些耗时的方法进行仪器化工作,例如org/json/JSONObject.toString()
。
方法的原始调用
public class JSONUsage {
public void callToString() {
JSONObject jsonObject = new JSONObject();
String a = jsonObject.toString();//original call
System.out.println(a);
}
}
仪器化之后
public class JSONUsage {
public void callToString() {
JSONObject jsonObject = new JSONObject();
// **important!**
//pass the instance as an param, replace the call to a static method
String a = JSONReplacement.jsonToString(jsonObject);
System.out.println(a);
}
}
public class JSONReplacement {
public static String jsonToString(JSONObject jsonObject) {
//do the time caculation
long before = System.currentTimeMillis();
String ret = jsonObject.toString();
long elapsed = System.currentTimeMillis() - before;
return ret;
}
}
Using ASM framework 3.0
ClassReader cr = new ClassReader("JSONUsage");
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
ReplaceClassVisitor replaceClassVisitor = new ReplaceClassVisitor(cw);
cr.accept(replaceClassVisitor, ClassReader.EXPAND_FRAMES);
问题:如何使用ASM API获得通用解决方案?
public class ReplaceClassVisitor extends ClassAdapter {
public ReplaceClassVisitor(ClassVisitor cv) {
super(cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new MethodReplaceMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc);
}
private static final class MethodReplaceMethodVisitor extends GeneratorAdapter {
public MethodReplaceMethodVisitor(MethodVisitor mv, int access, String name, String desc) {
super(mv, access, name, desc);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
//org/json/JSONObject.toString() here is a example,
//i want a general instruction
if (owner.equals("org/json/JSONObject") && name.equals("toString")) {
replaceCall(opcode, owner, name, desc);
}
}
private void replaceCall(int opcode, String owner, String name, String desc) {
//how can i have a general asm instruction to manipulate this method call?
}
}
}