ASM案例 - 如何判斷一個類是枚舉類

前言

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

相關文章
相關標籤/搜索