asm是操做class字节码的框架,经常用于运行期修改字节码实现特定功能, 好比aop, 好比jacoco的覆盖率插桩.
此次的需求是经过class文件去判断是不是枚举类.
如何经过asm读一个class文件呢?java
public static void main(String[] args) { try { FileInputStream in = new FileInputStream("D://StatusTypeEnum.class"); ClassReader cr = new ClassReader(in); } catch (IOException e) { e.printStackTrace(); } }
import jdk.internal.org.objectweb.asm.ClassReader;
jdk内置了asm相关的操做类,因此很是方便.
如何看是否是枚举类
思路:
1) 枚举类是默认继承了 java.lang.Enum, 查看父类linux
ClassReader cr = new ClassReader(in); String superName = cr.getSuperName();
实际上不够正确, 由于Enum类也能够在实现别的接口.
2)经过Access_Flags去查看.web
ClassReader cr = new ClassReader(in); int access = cr.getAccess();
access_flags 描述的是当前类(或者接口)的访问修饰符, 如public, private等,(参考: https://blog.csdn.net/u014490683/article/details/22745799)
咱们用javap -v StatusTypeEnum.class 解析当前类的字节码,获得以下:框架
public final class StatusTypeEnum extends java.lang.Enum<StatusTypeEnum> minor version: 0 major version: 54 flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_ENUM
看到没, 有4个flags, 调用Opcodes.ACC_PUBLIC 就能够看到这个int值是多少..net
int ACC_PUBLIC = 1; int ACC_PRIVATE = 2; int ACC_PROTECTED = 4; int ACC_STATIC = 8; int ACC_FINAL = 16; int ACC_SUPER = 32; int ACC_SYNCHRONIZED = 32; int ACC_VOLATILE = 64; int ACC_BRIDGE = 64; int ACC_VARARGS = 128; int ACC_TRANSIENT = 128; int ACC_NATIVE = 256; int ACC_INTERFACE = 512; int ACC_ABSTRACT = 1024; int ACC_STRICT = 2048; int ACC_SYNTHETIC = 4096; int ACC_ANNOTATION = 8192; int ACC_ENUM = 16384; int ACC_MANDATED = 32768; int ACC_DEPRECATED = 131072;
实际上,cr.getAccess()
的返回值在这个例子中就会是cr.getAccess()=Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL+ Opcodes.ACC_SUPER+ Opcodes.ACC_ENUM
也就是16433.
你会发现flags的值会是2倍关系,只有这样设置才能从一个access值反推出惟一的flags.(在linux系统的rwx权限里也有殊途同归之妙)
那么,如今如何去判断一个类是抽象类?相比你已经会了.code