How can I apply the AdviceAdapter that I wrote?

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 concise and confusing, to say the least. I understood this a lot, but an extensive Google search did not show how what I expect to do with this class is now that I created it.

How to make this code apply to my objects at runtime?

0
source share
1 answer

I have compiled an example of quick code here: gist.github.com/VijayKrishna/1ca807c952187a7d8c4d , which shows how to use the method adapter through the corresponding visitor / adapter class.

So, you first β€œcall” the class adapter (say, from the 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); 

Then follow this by adapting the methods as follows in the class-adapter visitMethod :

 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 whole code snippet in case the essence is not available:

 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. } } } 
+1
source

Source: https://habr.com/ru/post/943696/


All Articles