千家信息网

Annotation Processor 处理器问题如何深度定位

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,Annotation Processor 处理器问题如何深度定位,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。什么是 Annotat
千家信息网最后更新 2026年10月31日Annotation Processor 处理器问题如何深度定位

Annotation Processor 处理器问题如何深度定位,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

什么是 Annotation Processor 构建问题

写过自定义注解处理器的老司机们乍一看这个问题觉得挺简单,是的,因为网上基本通篇都在教你怎么打日志,但是你有没有想过如果连日志都打印不出来的时候你怎么定位呢?譬如如下代码:

// 确认 META-INF/services/javax.annotation.processing.Processor 没问题 // 确认构建脚本没问题,确认注解 Bridge 有被使用且有参与构建 @AutoService(Processor.class) public class TestAnnotationProcessor extends AbstractProcessor {     public TestAnnotationProcessor() {         System.out.println("TestAnnotationProcessor constrator");     }      @Override     public synchronized void init(ProcessingEnvironment processingEnvironment) {         super.init(processingEnvironment);         System.out.println("TestAnnotationProcessor init");     }      @Override     public Set getSupportedAnnotationTypes() {         System.out.println("TestAnnotationProcessor getSupportedAnnotationTypes");         Set supported = new HashSet();         supported.add(Bridge.class.getCanonicalName());         return supported;     }      @Override     public boolean process(Set set, RoundEnvironment roundEnvironment) {         System.out.println("TestAnnotationProcessor process");         return true;     } }

运行构建后compileReleaseJavaWithJavac过程中没有先吐我 Annotation Processor 的任意一行日志,直接报错找不到我注解处理器产物类引用(即直接进行了 compile class 环节)。

你懵逼吗?反正我懵逼了!打印日志不好使了,哈哈,环境确认没问题,什么鬼,直接越过 Annotation Processor 进行 compile 了。

这时候就需要你稍微深入定位分析(撸javac源码的巨佬请自行飘过),前提就是你需要熟悉下 Annotation Processor 基本原理,然后我们通过一些额外的javac详细日志进行举例分析。

Annotation Processor 机制

注解和注解处理器是 JDK5 引入的机制,主要用来为类、方法、字段和参数等 Java 结构提供额外的信息。譬如常见的@Override就是仅仅对 Java 编译器生效的一个注解。Java 允许我们自定义注解,自定义的注解处理器就是用来处理这些自定义注解的(废话),注解处理器触发时机是由javac来处理的,所以整个javac过程的简要步骤如下图:

javac 主要步骤

可以看到,javac编译概要图主要分为如下几步:

  1. 把源文件解析为抽象语法树。

  2. 调用已注册的注解处理器。

  3. 如果注解处理器处理过程中生成了新的源文件,编译器重复第 1、2 步,当注解处理器不再生成新的源文件则进入最后一轮。

  4. 进入真正的 compile 字节码环节生成字节码。

如上就是注解处理器的核心机制,有了这个核心机制的认识我们就继续往下探索。

构建工具下 Annotation Processor 的本质

我们日常开发中(无论是 Java 后端还是 Android 移动端)总是多多少少会用到 JDK 提供的annotation processor能力,无论是什么构建工具(Gradle 或者 Maven 等)本质都是通过javac -processorpath命令参数显式指定哪些 Processer,或者显式声明META-INF/services/javax.annotation.processing.Processor来被javac发现并调用的(参见 google 的 AutoService 框架)。

正常情况下我们开发中使用及构建 Annotation Processor 技术都是上面几步走的方案,而且大多数照着网络上抄的都能正常工作,每次只用自己处理 process 就挺香的,因为只要按照规则声明放置,其他的 javac都能自己完美调用。

增强 javac 过程打印暴露问题

要解决一开始说的 Annotation Processor 中自己加的日志都不打印场景问题,我们需要获取一些额外的信息辅助定位。由于直接使用命令行javac的方式是最原始的操作,我们构建一般采用 Gradle,而 Gradle 的本质还是调用javac,所以下面我们以 Gradle 为例来分析如何定位 Annotation Processor 问题。

下面简单粗暴点就是直接在根目录的build.gradle中给所有模块添加参数:

// 参数可选,重点是 -verbose -XprintRounds -XprintProcessorInfo allprojects {     gradle.projectsEvaluated {         tasks.withType(JavaCompile) {             options.compilerArgs << "-Xlint" << "-verbose" << "-XprintRounds" << "-XprintProcessorInfo" << "-Xmaxerrs" << "100000"         }     } }

你也可以仅仅在自己有注解处理器的模块中添加,与上面一样,只要加给JavaCompile的参数就行。这里的参数其实就是我们平时命令行javac是否的参数,不懂的可以去命令行执行下javac -help观摩下含义吧,如下(JDK8,不同版本 JDK 略有差异):

yan@yanDeMackbookPro:~$ javac -help 用法: javac   其中, 可能的选项包括: -g                         生成所有调试信息 ...... -verbose                   输出有关编译器正在执行的操作的消息 ...... -processor [,,...] 要运行的注释处理程序的名称; 绕过默认的搜索进程 -processorpath <路径>        指定查找注释处理程序的位置 ......

至于脚本中其他几个在javac -help中没有的参数可以看下官方文档https://docs.oracle.com/en/java/javase/11/tools/javac.html ,里面详细解释了参数含义。

添加上面参数后一定要将你的构建日志追加到一个磁盘文件中,因为日志会变得非常庞大,同时也变得很容易定位问题。

通过构建日志分析定位问题

执行你的构建任务,完毕后分析定位主要分为如下几个步骤,每一步都是一种场景的定位,循序渐进定位分析即可。

1.在你的日志中搜索你的 Processor 类名,譬如TestAnnotationProcessor.class,看到的日志会是如下。

// 如果你的注解处理器在项目中是源码形式的日志 [loading RegularFileObject[/home/user/yan/test/target/classes/cn/yan/test/TestAnnotationProcessor.class]]  // 如果你的注解处理器在项目中是依赖 jar 形式的日志 [loading ZipFileIndexFileObject[....../test.jar(cn/yan/test/TestAnnotationProcessor.class)]]

分析: 如果你的日志中搜不到上面信息,说明你的注解处理器没有被添加到javac的 classpath 中。一般问题就是你的META-INF/services/javax.annotation.processing.Processor声明有问题,javac无法找到你的注解处理器。有些同学可能是通过 google 的 AutoService 来生成META-INF/services/javax.annotation.processing.Processor的,这种情况下也要自己检查是否 OK(譬如之前安卓中 AGP 有一段时间的中间过渡版本就修改了 classpath,需要手动将 compile 改成 annotationProcessor 才行)。

2.在你的日志中搜索Round关键字,建议直接搜Round 1:这样的格式容易点,看到的日志会是如下。

Round 1:         input files: {cn.yan.test.Application, ......, cn.yan.test.UseMarkedAnnotation}                 annotations: [java.lang.Override, cn.yan.annotation.Bridge]                 last round: false

上面日志中的input files:部分是扫到的你的源码,annotations:部分就是扫到你代码中使用了哪些注解,如果你注解处理器声明了要处理这种注解(譬如@cn.yan.annotation.Bridge),则日志如上才是正常的。

分析: 如果你日志中没搜到上面的Round,则说明javac没有触发调用任何注解处理器(无论是你写的还是依赖三方框架的),最大的可疑点就是检查下自己有没有禁用javac注解处理器,也就是确认javac执行时没有-proc:none参数。如果你的日志中有Round,但是input files:和annotations:没有你的注解类和使用类,则说明你没有在代码中使用你注解处理器要处理的注解。

3.在你的日志中搜索Loaded cn.yan.test.TestAnnotationProcessor关键字,看到的日志会是如下。

[Loaded cn.yan.test.TestAnnotationProcessor from file:/home/user/yan/test/target/classes/cn/yan/test/TestAnnotationProcessor.class]

分析: 如果你看不到上面这行日志,说明你的注解处理器类自己没有被加载成功,为什么没有我也不知道怎么分析了,但是至少说明没加载成功,你可能需要仔细核对哪里不规范或者不合法导致的了。

上面都排查完了,如果还是找不到问题原因,不妨换个思路,去仔细检查下你参与构建的普通 java 文件,是否存在语法错误或者什么问题(譬如常量没声明等);如果有,解决完了再试试,别问我为什么,我也没有深入研究javac这块源码,只是我遇到过,且也没有异常堆栈信息,最终发现是合并解决冲突后代码少了一个变量声明,就是单纯的越过了 Annotation Processor 过程直接进行 compile to class 流程了)。

这个技能有什么鸟用?

不瞒你说,我也算是老司机了,好些年前 Annotation Processor 就玩的很 6 了,但是最近项目升级构建和 Java8 及 androidX 支持后 merge 了下代码,然后项目中的注解处理器、dataBinding 全部都不工作了,更可气的是,这个不工作是真的很吝啬,什么错误堆栈都没有,大致如下奇葩构建日志:

FAILURE: Build failed with an exception.  * What went wrong: Execution failed for task ':test:compileReleaseJavaWithJavac'. // 本来这里该先吐我注解处理器内部的日志,然后才继续 javac 编译,实际什么都没吐 > Compilation failed; see the compiler error output for details. * Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':moffice:compileReleaseJavaWithJavac'.     at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$1(ExecuteActionsTaskExecuter.java:200)     ...... Caused by: org.gradle.api.internal.tasks.compile.CompilationFailedException: Compilation failed; see the compiler error output for details.     at org.gradle.api.internal.tasks.compile.JdkJavaCompiler.execute(JdkJavaCompiler.java:57)

Gradle 构建命令已经添加了各种详细参数供查看堆栈和详细日志,但奇妙的事情就是他走到compileReleaseJavaWithJavac就直接出错了,前后没有任何错误提示(有的只是一坨 Gradle 自己的 task 调用链)。我特么大意了,我就同步了下代码,编不过就编不过啊,你倒是提示下问题啊!啥也不提示直接干到 compile class 环节了,跳过了 Annotation Processor 流程,这就很恼火了。好在按照上面方式定位修复了,哈哈。

关于Annotation Processor 处理器问题如何深度定位问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

处理 注解 日志 处理器 问题 定位 参数 就是 分析 代码 信息 命令 过程 编译 机制 源码 还是 项目 搜索 生成 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 南京欣网互联网络科技有限公司 互联网科技行业发展 华中科技大学互联网 西藏七维空间互联网科技有限公司 广州优美互联网科技 互联网科技寓意 南山科技园互联网公司有哪些 宝灵互联网科技有限公司 苏州铭阳互联网科技有限公司 互联网在线教育科技创业 华中科技大学互联网的牛人 黑科技 体验场景 互联网大会 领航科技大厦互联网公司 山东大美朱楼互联网科技有限公司 福建互联网展示科技馆设计 福州德业互联网科技 普陀区互联网教育科技管理办法 北京军民互联网科技公司 互联网科技对化妆品行业 互联网科技大佬云集 互联网与科技 期待互联网科技 贷财互联网科技 撒么互联网科技公司 镁科技互联网资讯平台 成都玖崟互联网科技有限公司乐商圈怎么样 众安科技工业互联网合作 元气玛特互联网科技公司是外包吗 珠海东科互联网科技有限公司 湖北辰鑫科技互联网
0