一、介紹
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實例。可以將其視爲事件過濾器。
下一節將通過具體示例顯示如何使用這些組件來生成和轉換類