要在 Java 字节码中保留自定义注解,必须将 @Retention 设为 RetentionPolicy.RUNTIME;否则默认 SOURCE 策略导致注解不进入字节码,无法通过反射读取。

要在 Java 字节码中保留自定义注解,关键在于正确设置注解的 @Retention 策略为 RetentionPolicy.RUNTIME。只有这样,注解信息才会被编译器写入 .class 文件,并在运行时通过反射读取。
1. 正确定义自定义注解(带 RUNTIME 保留策略)
必须显式使用 @Retention(RetentionPolicy.RUNTIME),否则默认是 SOURCE(仅保留在源码,不进字节码)。
示例:
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) // ✅ 必须!才能进字节码
@Target(ElementType.METHOD) // 可选:限制使用位置
@Documented
public @interface MyLog {
String value() default "";
boolean enabled() default true;
}
2. 在类或方法上使用该注解
注解生效的前提是它被实际应用到某个程序元素上,且该元素未被编译器优化移除(如 private 未被调用的方法一般仍会保留在字节码中)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
示例:
public class UserService {
@MyLog(value = "createUser", enabled = true)
public void createUser(String name) {
System.out.println("Creating: " + name);
}
}
3. 验证注解是否进入字节码
编译后,可通过以下方式确认注解已写入 .class:
- 用
javap -v UserService.class查看常量池和方法属性,搜索MyLog或RuntimeVisibleAnnotations - 在代码中用反射验证:
method.getAnnotation(MyLog.class)能返回非 null 实例 - 使用工具如 jclasslib、IntelliJ 的 “Show Bytecode” 功能直观查看注解属性
4. 注意事项与常见误区
-
不要只写 @Retention(RetentionPolicy.CLASS):它虽写入字节码,但无法通过反射获取(
getAnnotation()返回 null) - @Target 不影响保留性,但若目标类型不匹配(如把方法注解加到类上),编译会报错
- 如果使用了 AOP、Lombok 或其他字节码增强工具,需确认它们未过滤或清除你的注解
- 模块化(module-info.java)中无需额外导出注解,只要注解类在类路径上即可被反射识别

















