ASM核心API简介(2)

发表于2019-08-02,长度2071, 182个单词, 5分钟读完
Flag Counter

ASM 中生成和转换字节码的API主要是基于抽象类 ClassVisitor 的。这里讲一下 ClassVisitor 的用法。

有很多平台都提供了这个类,甚至包括Java自己。注意ASM的包名是org.objectweb.asm

方法定义

ClassVisitor 的方法如下:

public abstract class ClassVisitor {
    public ClassVisitor(int api);
    public ClassVisitor(int api, ClassVisitor cv);
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces);
    public void visitSource(String source, String debug);
    public void visitOuterClass(String owner, String name, String desc);
    AnnotationVisitor visitAnnotation(String desc, boolean visible);
    public void visitAttribute(Attribute attr);
    public void visitInnerClass(String name, String outerName, String innerName, int access);
    public FieldVisitor visitField(int access, String name, String desc, String signature, Object value);
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions);
    void visitEnd();
}

每个方法都对于类文件中的一块结构(连名字也一样),这也是它为啥叫元素模型的原因。 简单的块通过没有返回值的方法访问,参数就是这一块的内容。比较复杂的块通过返回备用类的方法访问,分别是visitAnnotation返回AnnotationVisitor, visitField返回 FieldVisitor,visitMethod返回MethodVisitor。这些返回类型会递归使用这样的规则,比如FieldVisitor也包含类似的方法:

public abstract class FieldVisitor {
    public FieldVisitor(int api);
    public FieldVisitor(int api, FieldVisitor fv);
    public AnnotationVisitor visitAnnotation(String desc, boolean visible);
    public void visitAttribute(Attribute attr);
    public void visitEnd();
}

调用顺序

ClassVisitor 中的方法只能以以下顺序调用,这个顺序也在ClassVisitor的javadoc中说了:

visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*
( visitInnerClass | visitField | visitMethod )*
visitEnd

意思就是必须先调用且调用一次visit方法,然后是0或1次visitSource,然后是0或1次visitOuterClass,然后是0或多次visitAnnotation或visitAttribute,然后是0或多次visitInnerClass或visitField或visitMethod,最后必须调用一次visitEnd。

核心组件

基于ClassVisitor,ASM 提供了3个核心组件用于生成和转换字节码:

  • ClassReader类是事件生产者(我们这不是事件模型嘛),它会解析字节数组,调用accept方法。accept方法接收一个ClassVisitor对象,它的各个visitXXX方法会被调用。
  • ClassWriter类是事件消费者,它是ClassVisitor的子类,会构建字节码文件。字节数组是通过toByteArray方法产生的。
  • ClassVisitor 是事件过滤器,它会把各种请求委托给别的 ClassVisitor 实例。

后面我们开始将它们的用法。

Written on August 2, 2019
分类: dev, 标签: java asm
如果你喜欢,请赞赏! davelet