问题
I have the following class:
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.AdviceAdapter;
public class NotEmptyAdvice extends AdviceAdapter
{
protected NotEmptyAdvice(final MethodVisitor visitor, final int i, final String s, final String s2)
{
super(visitor, i, s, s2);
}
@Override
protected void onMethodEnter()
{
super.mv.visitVarInsn(ALOAD, 1);
super.mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "isEmpty", "()Z" );
super.mv.visitVarInsn(IFEQ, 1);
super.mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
super.mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
super.mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");
super.mv.visitVarInsn(ALOAD, 1);
super.mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;" );
super.mv.visitLdcInsn(" can not be empty!");
super.mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;" );
super.mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;" );
super.mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V");
super.mv.visitInsn(ATHROW);
}
}
The asm
library documentation is terse and obfuscated to say the least. I figured this much out, but extensive googling has not revealed how what I am expected to do with this class now that I have created it.
How to get this code to be applied to my objects at runtime?
回答1:
i have put together a quick code example here: gist.github.com/VijayKrishna/1ca807c952187a7d8c4d, that shows how to use a method adaptor, via its corresponding class-visitor/class-adaptor.
In summary, you first "invoke" the class adapter (say from within a main method) as follows:
ClassReader cr = new ClassReader(in);
ClassWriter cw = new ClassWriter(ClassReader.EXPAND_FRAMES);
ReturnAdapter returnAdapter = new ReturnAdapter(cw, className);
cr.accept(returnAdapter, 0);
You then follow it up adapting the methods as follows in the class-adaptor's visitMethod
method:
public MethodVisitor visitMethod(int access ... ... ... ) {
MethodVisitor mv;
mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv = new MethodReturnAdapter(Opcodes.ASM4, className, access, name, desc, mv);
return mv;
}
Here is the entire code snippet in case the gist is inaccessible:
public class ReturnAdapter extends ClassVisitor {
private String className;
public ReturnAdapter(ClassVisitor cv, String className) {
super(Opcodes.ASM4, cv);
}
@Override
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions) {
MethodVisitor mv;
mv = cv.visitMethod(access, name, desc, signature, exceptions);
mv = new MethodReturnAdapter(Opcodes.ASM4, className, access, name, desc, mv);
return mv;
}
public static void main(String[] args) throws IOException {
String classFile = args[0];//path of the class file
String className = args[1];//name of the class
File inFile = new File(classFile);
FileInputStream in = new FileInputStream(inFile);
// adapting the class.
ClassReader cr = new ClassReader(in);
ClassWriter cw = new ClassWriter(ClassReader.EXPAND_FRAMES);
ReturnAdapter returnAdapter = new ReturnAdapter(cw, className);
cr.accept(returnAdapter, 0);
}
}
/**
* Method Visitor that inserts code right before its return instruction(s),
* using the onMethodExit(int opcode) method of the AdviceAdapter class,
* from ASM(.ow2.org).
* @author vijay
*
*/
class MethodReturnAdapter extends AdviceAdapter {
public MethodReturnAdapter(
int api,
String owner,
int access,
String name,
String desc,
MethodVisitor mv) {
super(Opcodes.ASM4, mv, access, name, desc);
}
public MethodReturnAdapter(
MethodVisitor mv,
int access,
String name,
String desc) {
super(Opcodes.ASM4, mv, access, name, desc);
}
@Override
protected void onMethodEnter(int opcode) {
mv.visitVarInsn(ALOAD, 1);
// and/or any other visit instructions.
}
@Override
protected void onMethodExit(int opcode) {
if(opcode != Opcodes.ATHROW) {
mv.visitVarInsn(Opcodes.ALOAD, 1);
// and/or any other visit instructions.
}
}
}
来源:https://stackoverflow.com/questions/23873481/how-do-i-apply-the-adviceadapter-i-have-written