java注解在字节码中以结构化元数据形式存于attributes区,按@retention策略分三类:runtime存runtimevisibleannotations、class存runtimeinvisibleannotations、source不进字节码;所有属性值须为编译期常量。

Java注解在字节码里不是可执行代码,而是以结构化元数据形式写入类文件的特定属性表中。它的存在与否、位置和可访问性,完全由@Retention策略在编译那一刻就决定好了。
注解被编译成字节码时的三类归宿
javac 编译器根据注解的 @Retention 值,把注解信息写进 class 文件的不同属性表:
-
RUNTIME 级注解 → 写入
RuntimeVisibleAnnotations属性表。JVM 加载类时会保留在内存中,反射能拿到。 -
CLASS 级注解(默认) → 写入
RuntimeInvisibleAnnotations属性表。字节码里有,但 JVM 类加载阶段主动丢弃,运行时反射查不到。 -
SOURCE 级注解 → 不进入字节码,编译完即消失。只供 javac 在编译期做检查或生成辅助代码(如
@Override校验、APT 工具生成类)。
字节码中的实际存储结构
class 文件末尾的 attributes 区域包含注解信息。每个注解条目记录:
- 类型索引(
type_index),指向常量池中该注解的全限定名(如Lcom/example/MyAnnotation;); - 元素值对数量(
num_element_value_pairs),即注解属性个数; - 每个属性名和编译期确定的常量值(支持基本类型、String、Class、枚举、其他注解、以及它们的数组)。
注意:所有属性值必须是编译期常量,不能是运行时计算结果,这是字节码能静态存储的前提。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
注解接口在字节码里的本质形态
你写的 public @interface MyAnno { String value(); },编译后不会生成类,而是生成一个继承 java.lang.annotation.Annotation 的接口:
- 接口中每个属性变成一个无参抽象方法(
value()); - JVM 运行时为该接口动态生成代理实现类,把字节码里读出的属性值填充进去;
- 反射调用
getAnnotation()返回的,就是这个动态代理对象。
验证方式:用 jclasslib 或 javap 查看
编译一个带注解的类后,可用工具直观确认:
- 用 jclasslib 打开 .class 文件 → 展开左侧 Attributes → 查看
RuntimeVisibleAnnotations表项; - 命令行执行
javap -v MyClass.class→ 搜索RuntimeVisibleAnnotations或RuntimeInvisibleAnnotations字段。
你会看到注解类型、属性名、以及硬编码的字符串或数字字面量——没有逻辑,只有数据。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










