2

ClassAdapterasm フレームワークを使用してバイトコード トランスフォーマーを作成しています。クラスにカスタム アノテーションが存在する場合は、いくつかのメソッドを追加して、クラスにインターフェイスを実装させたいと考えています。メソッドの追加は正常に機能していますが、クラスにインターフェイスを実装させる最善の方法は何だろうと思っています。visitAnnotationは の後にしか呼び出されないためvisit、どうにかして super 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
        }
    }
}
4

1 に答える 1

2

ClassNode API と ClassAdapter API を組み合わせて使用​​することになりました。まず、クラス ファイルが ClassNode に解析されます。

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

次に、cn.visibleAnnotation または cn.invisibleAnnotations に注釈が含まれているかどうか、および追加したいインターフェイスがクラスに既に実装されているかどうかを確認できます。その場合、2 番目のステップはスキップできます。ClassNode は、質問のように ClassAdapter API を使用して変換できます。

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

私の質問の理由であるパッケージのドキュメントのメモには、これらの API 間の大きなパフォーマンスの違いが記載されていました。

クラスの読み取り、「変更」、および書き込みは、ClassAdapter を使用する方が、ClassNode を使用する場合よりもほぼ 2 倍高速です。...これが、可能な場合はこのクラスアダプターを使用しないことをお勧めする理由でもあります。

それをもう一度読み直した後、違いは ClassNode を使用してバイトコードを操作することにあるようです。ただし、このハイブリッド ソリューションのベンチマークは行いませんでした。

于 2011-03-29T22:51:48.210 に答える