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