必须将@Retention设为RUNTIME才能被反射读取,因为CLASS策略下注解仅存于字节码而不加载进JVM元空间,反射API无数据可访问;SOURCE编译后即消失;只有RUNTIME策略使注解写入RuntimeVisibleAnnotations并进入运行时内存。

因为 JVM 在运行时根本不会把 @Retention(RetentionPolicy.CLASS) 的注解加载进内存,反射 API 没有数据可读。
注解没“活到运行时”
RetentionPolicy.CLASS 表示注解只保留在 .class 文件里,属于“编译期可见、运行期隐身”的状态。JVM 加载类时,会忽略这类注解,不将其注入元空间(Metaspace),所以 method.getAnnotation()、clazz.isAnnotationPresent() 等方法永远返回 null——不是查不到,是压根不存在于运行时环境。
- 你用
javap -v能在字节码里看到它(通常出现在RuntimeInvisibleAnnotations属性中) - 但 JVM 不解析它,也不暴露给反射机制
- 这种设计本意就是让注解仅服务构建工具(如代码检查、字节码增强),不带来运行时开销
RUNTIME 才是反射的“入场券”
只有 @Retention(RetentionPolicy.RUNTIME) 的注解,才会被写入 RuntimeVisibleAnnotations 属性,并在类加载阶段进入 JVM 元空间,成为反射 API 可访问的元数据。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- SOURCE:编译完就丢,.class 里根本没有
- CLASS:.class 里有,但 JVM 不加载,反射不可见
- RUNTIME:.class 里有 + JVM 加载进内存 + 反射可读
改了也没用?那是没改对
遇到反射拿不到注解,不能靠改调用方代码绕过,必须回到注解定义本身:
立即学习“Java免费学习笔记(深入)”;
- 找到自定义注解类,确认
@Retention值确实是RetentionPolicy.CLASS - 改成
@Retention(RetentionPolicy.RUNTIME) - 重新编译该注解类(不是只编译使用它的类)
- 确保依赖它的模块也刷新 classpath 或重新构建(尤其多模块 Maven/Gradle 项目)
第三方注解无法修改怎么办
如果注解来自外部库且生命周期固定为 CLASS:
- 查文档看是否有配套的 RUNTIME 版本(例如某些框架提供
@XXXRuntime) - 改用其他运行时可读的元数据方式:方法命名约定、接口实现标记、配置文件映射
- 借助 ASM 或 Byte Buddy 在构建期扫描字节码,生成运行时可用的辅助类(非标准反射路径,需额外维护)

















