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权限里也有异曲同工之妙)
那么,现在如何去判断一个类是抽象类?相比你已经会了.

转载于:https://www.cnblogs.com/zhhiyp/p/10447579.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值