ASM核心API 类解析用法(3)
前面说过,asm提供了三个核心类:ClassReader、ClassWriter 和 ClassVisitor。这里先讲一下类的读取和解析,用到第一个和第三个类。
本篇中用到的例子都上传到了https://github.com/davelet/asm101上
读取类最简单的方法是将类的全路径名传给ClassReader。我们新建一个类,比如是com.asmtest.asm.Klazz,内容写成最简单的就行:
package com.asmtest.asm;
public class Klazz{
}
然后读取这个类:
ClassReader cr = new ClassReader("com.asmtest.asm.Klazz");
就这么简单,类信息就可以被访问了。比如要访问类的名称:
String className = cr.getClassName();
System.out.println(className);
会输出:com/asmtest/asm/Klazz
。
再比如要查看一下这个类实现了哪些接口,继承了哪个类:
System.out.println(Arrays.toString(cr.getInterfaces()));
System.out.println(cr.getSuperName());
getInterfaces()
方法拿到的是类实现接口的数组。返回如下:
[]
java/lang/Object
可以看到接口数组为空,也就是没实现接口;而父类是Object。
下面看一下ClassReader 的方法组成。
ClassReader 提供的方法不少,但是常用的不多,除了上面几个就剩下getAccess()
,这个方法是查看类的访问控制级别的。
可以调用一下看看,返回的是33。可以看Oracle的jvm规范文档 https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1, 列出了类的标志符;33 = 32 + 1,说明是两个标志的组合,1 是public,32是acc_super。32是没什么意义的,所有的类都会包含32。如果一个类不是Public的,那它的访问级别就只是32。
ClassReader 有5个构造方法,其中4个是public的。上面我们用的是最简单的一个,它的实现是依次调用其他三个Public构造器,最后调用非public构造器。构造器的内容都是把类的所有信息都拿出来,这些信息可以通过ClassReader提供的其他方法访问。
ClassReader 还提供了很多低阶的方法,一般是用于查看属性信息的。实现最复杂的一个方法是readCode
,用于获取code属性。这些低阶方法中,最简单的一个是getItemCount()
,我们可以试一下:
System.out.println(cr.getItemCount());
打印结果是16,这个是类的常量池的大小 + 1。可以用javap -c -v查看字节码文件,能够看到常量池里面有15个对象。
上面是ClassReader的初步介绍。结合ClassVisitor可以实现更复杂的功能,后面我们再介绍。
