java类加载机制与注解处理器无直接配合:前者在运行时加载.class文件,后者在编译期由javac调用生成.java源文件,二者分属不同阶段、环境与生命周期,仅通过生成代码的后续编译间接衔接。

Java 类加载机制和注解处理器不直接配合工作,它们发生在完全不同的阶段、不同环境,且彼此隔离。
注解处理器运行在编译期,与类加载无关
注解处理器由 javac 在编译源码时调用,此时还没有生成完整的 .class 文件,更没有进入 JVM 的类加载流程。它只读取 源代码中的注解元素(如 @GenerateBuilder),通过 ProcessingEnvironment 获取类型信息,然后用 Filer 生成新的 .java 源文件。这些生成的源文件会参与后续的编译轮次,但整个过程不涉及任何类加载器(ClassLoader)、也不触发 defineClass 或 loadClass。
- 注解处理器无法看到运行时类结构,也不能反射访问目标类
- 它不能修改已有类字节码,只能新增源文件(Lombok 是特例,依赖编译器内部 API 操作 AST)
- 其生命周期止于编译结束,与 JVM 启动、类加载器层次(Bootstrap/Extension/App)完全无关
类加载机制只处理已存在的 .class 文件
类加载发生在程序运行前或运行中,由 JVM 的类加载子系统完成:从磁盘或网络读取 .class 字节码,校验、准备、解析、初始化。此时注解是否保留,取决于 @Retention 策略:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
-
@Retention(RetentionPolicy.SOURCE):注解早已被javac丢弃,类加载器根本看不到 -
@Retention(RetentionPolicy.CLASS):注解保留在字节码的RuntimeVisibleAnnotations属性中,但类加载器不会将其暴露给 Java 代码(反射不可见) -
@Retention(RetentionPolicy.RUNTIME):注解被加载进方法区,并可通过Class.getAnnotations()反射读取——这是 Spring、JUnit 等框架运行时处理注解的基础
二者唯一间接关联:生成的代码参与类加载
注解处理器生成的 .java 文件(如 PersonBuilder.java)会被 javac 编译成 PersonBuilder.class,这个 class 文件最终和其他类一样,由类加载器加载进 JVM。但这只是“结果上的衔接”,不是机制上的协作:
- 生成的类不依赖原始被注解类是否已被加载
- 类加载器并不知道该类是由注解处理器生成的
- 若生成类引用了尚未编译的类,会导致编译失败,而非类加载失败
简单说:注解处理器是 javac 的插件,负责“写代码”;类加载器是 JVM 的组件,负责“读字节码”。一个在编译流水线里,一个在运行时引擎里,中间隔着完整的编译输出环节。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










