ASM核心API 类解析用法(3)

发表于2019-08-14,长度1341, 105个单词, 3分钟读完
Flag Counter

前面说过,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可以实现更复杂的功能,后面我们再介绍。

Written on August 14, 2019
分类: dev, 标签: java asm
如果你喜欢,请赞赏! davelet