比反射更快!使用ASM获取class信息(ClassReader)
通常我们想要在java运行时获取class的信息时,通常使用反射的方式来获取其中的属性,方法,注解等信息。通常是这样的:
Class<Aoo> aooClass = Aoo.class;
//获取declaredMethod
for (Method declaredMethod : aooClass.getDeclaredMethods()) {
System.out.println("declaredMethod.getName() : " + declaredMethod.getName());
System.out.println("declaredMethod.getReturnType(): " + declaredMethod.getReturnType().getName());
}
//获取DeclaredField
for (Field field : aooClass.getDeclaredFields()) {
System.out.println("field.getName() : " + field.getName());
System.out.println("field.getType() : " + field.getType().getName());
}
//获取Annotation
for (Annotation annotation : aooClass.getAnnotations()) {
System.out.println("annotation.annotationType() : " + annotation.annotationType().getName());
}
...
获取其他的一些信息
虽然用起来也是很好用,api也不复杂,但是由于使用反射对性能的开销比较大,性能不是很好。我们可以通过asm来获取class中的信息。
从官网抄的介绍:
ASM是一个通用的Java字节码操作和分析框架。它可以用于修改现有类或直接以二进制形式动态生成类。ASM提供了一些常见的字节码转换和分析算法,可以从中构建自定义复杂转换和代码分析工具。ASM提供与其他Java字节码框架类似的功能,但专注于 性能。因为它的设计和实现尽可能小而且快,所以它非常适合在动态系统中使用(但当然也可以以静态方式使用,例如在编译器中)。
嗯~
看起来很不错,怎么用呢?
添加依赖
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>7.1</version>
</dependency>
读取class需要的对象
现在的asm版本是7.1,所以这一内容都以7.1的版本为主。
因为我们要做的是获取class中的各种信息,所以我们需要用到下面一些对象:
- ClassReader :按照Java虚拟机规范中定义的方式来解析class文件中的内容,在遇到合适的字段时调用ClassVisitor中相对应的方法。
- ClassVisitor:java中类的访问者,提供一系列方法由ClassReader调用。是一个抽象类,我们在使用的时候需要继承此类。使用此对象的时候需要指定asm api的版本。
- ModuleVisitor:Java中模块的访问者,作为ClassVisitor.visitModule方法的返回值,要是不关心模块的使用情况,可以返回一个null。使用此对象的时候需要指定asm api的版本。
- AnnotationVisitorÿ