【问题标题】:Adding an interface to a transformed class if annotation is present如果存在注释,则将接口添加到转换后的类
【发布时间】:2011-03-24 00:43:02
【问题描述】:

我正在使用 asm 框架的ClassAdapter 编写字节码转换器。如果类上存在自定义注释,我想添加一些方法并使类实现接口。添加方法工作正常,但我想知道让类实现接口的最佳方法是什么。由于visitAnnotation 仅在visit 之后调用,我需要以某种方式延迟调用超级访问方法并缓冲所有需要的信息直到那时。

有没有人实现过类似的东西?我是否应该为此使用 asm 的树 API,尽管包文档建议尽可能避免使用它?

这是转换的一般结构:

public class MyClassAdapter extends ClassAdapter {
    private String  classname;
    private boolean instrument;

    public PropertyChangeSupportAdapter(ClassVisitor cv) {
        super(cv);
    }

    @Override
    public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
        this.classname = name;
    }

    @Override
    public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
        if (desc.equals("Lmypackage/MyAnnotation;")) {
            instrument = true;
            System.out.println("Instrumenting " + classname);
        }
        return super.visitAnnotation(desc, visible);
    }

    @Override
    public void visitEnd() {
        if (instrument) {
            // add methods
        }
    }
}

【问题讨论】:

    标签: java instrumentation java-bytecode-asm


    【解决方案1】:

    我最终使用了 ClassNode 和 ClassAdapter api 的组合。首先将class文件解析成一个ClassNode:

    ClassReader cr = new ClassReader(inputStream);
    ClassNode cn = new ClassNode();
    cr.accept(cn, 0);
    

    然后可以检查 cn.visibleAnnotation 或 cn.invisibleAnnotations 是否包含我的注释,以及该类是否已经实现了我要添加的接口。在这种情况下,可以跳过第二步。然后可以使用 ClassAdapter api 转换 ClassNode,如问题中所示:

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    CheckClassAdapter ca = new CheckClassAdapter(cw);
    ClassVisitor cv = new PropertyChangeSupportAdapter(ca);
    cn.accept(cv);
    

    package documentation 的注释是我提出问题的原因,其中提到了这些 api 之间的巨大性能差异:

    使用 ClassAdapter 读取、“修改”和编写类几乎比使用 ClassNode 快两倍。 ...这也是为什么建议尽可能不要使用此类适配器的原因。

    再次阅读后,差异似乎来自使用 ClassNode 来操作字节码。但是,我没有对这种混合解决方案进行基准测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-11
      • 2014-01-09
      • 2010-11-18
      相关资源
      最近更新 更多