一、介绍
1.1 ClassVisitor抽象类
用于生成和转换已编译类的ASM API基于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();
}
此class中的每个方法对应于同名的class文件结构部分,如下所示:
1.2 FieldVisitor 抽象类
通过单个方法调用可以访问简单部分,该方法的参数描述其内容,并返回void。
内容可以具有任意长度和复杂度的节通过返回辅助访问者类的初始方法调用来访问。
visitAnnotation,visitField和visitMethod方法就是这种情况,它们分别返回AnnotationVisitor,FieldVisitor和MethodVisitor。
这些辅助类递归使用相同的原理。 例如,FieldVisitor抽象类中的每个方法(请参见图2.5)对应于具有相同名称的类文件子结构,并且visitAnnotation
与ClassVisitor中一样,返回一个辅助AnnotationVisitor。 创作
这些辅助访问者的用法以及用法将在后面章节再进行解释:实际上,本章仅限于可以单独使用ClassVisitor类解决的简单问题。
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();
}
1.3 ClassVisitor方法调用顺序和次数
必须按照该类的Javadoc中指定的以下顺序调用ClassVisitor类的方法:
visit visitSource? visitOuterClass? ( visitAnnotation | visitAttribute )*
( visitInnerClass | visitField | visitMethod )*
visitEnd
这意味着必须
- 首先调用
visit
, - 然后最多调用一次
visitSource
, - 然后最多一次调用
visitOuterClass
, - 然后按任意顺序按任意顺序访问任意多个
visitAnnotation
和visitAttribute
, - 然后按任意顺序任意调用任意数目 到
visitInnerClass
,visitField
和visitMethod
, - 并通过一次对
visitEnd
的调用终止。
1.4 生成和转换class的核心组件
ASM提供了三个基于ClassVisitor API的核心组件,用于生成和转换class:
- ClassReader类解析以字节数组形式给出的已编译的class文件,并在ClassVisitor实例上调用作为参数传递给其accept方法的相应visitXxx方法。 可以将其视为事件产生器。
- ClassWriter类是ClassVisitor抽象类的子类,该类直接以二进制形式构建编译的类。它产生一个包含已编译类的字节数组作为输出,可以使用toByteArray方法进行检索。可以将其视为事件消费者。
- ClassVisitor类将它收到的所有方法调用委托给另一个ClassVisitor实例。可以将其视为事件过滤器。
下一节将通过具体示例显示如何使用这些组件来生成和转换类
{{o.name}}
{{m.name}}