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


前言#

asm是操作class字節碼的框架,常常用於運行期修改字節碼實現特定功能, 比如aop, 比如jacoco的覆蓋率插樁.
這次的需求是通過class文件去判斷是否是枚舉類.
如何通過asm讀一個class文件呢?

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, 查看父類
ClassReader cr = new ClassReader(in);
String superName = cr.getSuperName();

實際上不夠正確, 因為Enum類也可以在實現別的接口.
2)通過Access_Flags去查看.

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值是多少.

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權限里也有異曲同工之妙)
那么,現在如何去判斷一個類是抽象類?相比你已經會了.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM