ASM包括主要三个类:
1、ClassReader : 负责从类文件中读取输入流,并依照固定的顺序调用 ClassVisitor 中声明的多个 visitorXxx的方法。
2、ClassVisitor : 抽象类,负责类内容的访问。
3、ClassWriter :负责生成byte[]字节流。ClassWriter是ClassVisitor的子类。
三者的依赖关系和继承关系如下图:
下面是一个例子
一、首先定义一个ClassVisitor的子类ClassPrinter,用于显示一个需要处理的类的信息。
package org.soachina; import static org.objectweb.asm.Opcodes.ASM4; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Attribute; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.MethodVisitor; public class ClassPrinter extends ClassVisitor { public ClassPrinter() { super(ASM4); } public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { System.out.println(name + " extends " + superName + " {"); } public void visitSource(String source, String debug) { } public void visitOuterClass(String owner, String name, String desc) { } public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return null; } 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) { System.out.println(" " + desc + " " + name); return null; } public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { System.out.println(" " + name + desc); return null; } public void visitEnd() { System.out.println("}"); } }
二、创建ClassReader实例,并将ClassVisitor的子类 ClassPrinter传给ClassReader
package org.soachina; import java.io.IOException; import org.objectweb.asm.ClassReader; public class ClassPrinterTest { public static void main(String args[]) throws IOException { ClassReader classReader = new ClassReader("java.lang.Runnable"); ClassPrinter cp = new ClassPrinter(); classReader.accept(cp, 0); } }
visit :必须有这个方法,第一个被调用。 visitSource:可选,如果有最多只能有一个。 visitOuterClass :可选,如果有最多只能有一个。 visitAnnotation 可选,任意多个,与 visitAttribute 顺序可以互换 visitAttribute 可选,任意多个 visitInnerClass 可选,任意多个,与 visitField 、visitMethod 顺序可以互换 visitField 可选,任意多个 visitMethod 可选,任意多个 visitEnd 必须有这个方法,最后被调用。