java - 如何应用我编写的AdviceAdapter?

标签 java java-bytecode-asm

我有以下类(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);
    }
}

asm 库文档至少可以说是简洁且困惑的。我想出了这么多,但是广泛的谷歌搜索并没有透露我现在已经创建了这个类,我应该如何处理它。

如何在运行时将此代码应用于我的对象?

最佳答案

我在这里整理了一个快速代码示例:gist.github.com/VijayKrishna/1ca807c952187a7d8c4d ,它展示了如何通过其相应的类访问者/类适配器来使用方法适配器。

总之,您首先“调用”类适配器(例如从主方法中),如下所示:

ClassReader cr = new ClassReader(in);
ClassWriter cw = new ClassWriter(ClassReader.EXPAND_FRAMES);
ReturnAdapter returnAdapter = new ReturnAdapter(cw, className);
cr.accept(returnAdapter, 0);

然后,您可以在类适配器的 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;
}
<小时/>

以下是完整的代码片段,以防无法访问要点:

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.
    }
  }
}

关于java - 如何应用我编写的AdviceAdapter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23873481/

相关文章:

java - Android - Opencv - 错误:(-215) u != 0 in function void cv::Mat::create

java - Eclipse libgdx导入无法解决

java - 如果在 ClassWriter 中设置了 COMPUTE_FRAMES,ASM 会跳过类

static-analysis - 是否有像 Java 字节码的 ASM 这样的 CIL 静态分析库?

java - 在 servlet 环境(Tomcat Web 服务器)中使用 OPENSAML2 时出现编码错误

java - setOnTouchListener 不适用于相对布局或 viewFlipper

java - Intellij 模块在重建时被遗忘

java - Java中如何找到方法调用的行号

java - 字节码操作以拦截设置字段的值

Java ASM如何读取LOAD或STORE字节码的值