asm-giude阅读笔记003(ASM核心API接口和对应组件---读取字节码)

亡梦爱人 提交于 2019-12-08 09:58:46

2.2 接口和组件

 

2.2.1 介绍

 

ASM API 生成和转换Java字节码的操作都是基于ClassVisitor这个接口的。这个接口中的方法的方法名都是与字节码文件中节的名字对应的。

 

ClassVisitor接口的代码清单:

 

public interface ClassVisitor {


    void visit(int version, int access, String name, String signature, String superName, String[] interfaces);


    void visitSource(String source, String debug);


    void visitOuterClass(String owner, String name, String desc);


    AnnotationVisitor visitAnnotation(String desc, boolean visible);


    void visitAttribute(Attribute attr);


    void visitInnerClass(String name, String outerName, String innerName, int access);


    FieldVisitor visitField(int access, String name, String desc, String signature, Object value);


    MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions);


    void visitEnd();


}

 

ClassVisitor接口中的方法的调用是有顺序的,这个顺序如下所示:

 

>调用visit方法

 

>最多调用一次visitSource

 

>最多调用一次visitOuterClass

 

>调用visitAnnotation、visitAttribute任意次

 

>调用visitInnerClass、visitField、visitMethod任意次

 

>调用visitEnd

 

ASM提供了3个基于ClassVisitor几口的核心组件,用于生成和转换类:

 

>ClassReader类,该类解析byte数组中的Java类字节码,并且负责调用ClassVisitor接口实例(作为参数传递给ClassReader的accept方法)中相应的的visitXXX方法。该类可以看做是一个事件生产者。

 

>ClassWriter类,该类实现了ClassVisitor接口,用于直接以二进制的形式构建已编译的类。可以从该类实例中获得一个包含字节码的byte数组。该类可以看做是一个事件消费者。

 

>ClassAdaptor类,该类实现了ClassVisitor接口,它通过委派的方式调用其他的ClassVisitor接口实例的方法来提供ClassVisitor接口所要求实现的方法。该类可以看做是一个事件过滤器。

 

下一节将给出具体的例子,来说明如何生成和转换类。

 

2.2.2 解析类

 

解析一个类,只需要ClassReader这一个组件。

 

举一个例子,打印指定类的字节码信息:

 

import java.io.IOException;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

 

public class ClassPrinter implements ClassVisitor {

 

    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("}");
    }

 

    public static void main(String[] args) throws IOException {

        ClassPrinter classPrinter = new ClassPrinter();

        ClassReader classReader = new ClassReader("java.lang.Object");

        classReader.accept(classPrinter, 0);

    }

 

}

 

运行上面的程序,如果没有错误出现的话,应该会输出如下内容:

 

java/lang/Object extends null {
 <init>()V
 registerNatives()V
 getClass()Ljava/lang/Class;
 hashCode()I
 equals(Ljava/lang/Object;)Z
 clone()Ljava/lang/Object;
 toString()Ljava/lang/String;
 notify()V
 notifyAll()V
 wait(J)V
 wait(JI)V
 wait()V
 finalize()V
 <clinit>()V
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!