You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JDK21自定义注解处理器无法访问jdk.compiler模块问题排查

解决JDK21中自定义注解处理器访问jdk.compiler内部包的权限问题

问题场景

参考Lombok实现逻辑,在JDK21中通过注解处理器初始化阶段调用implAddOpens方法,尝试打开jdk.compiler模块的相关包。但将自定义注解处理器用maven clean install打包后,在其他项目中使用时出现编译错误:

org.example.async.log.client.annotation.AsyncLogProcessor(位于未命名模块)无法访问com.sun.tools.javac.api.JavacTrees(位于jdk.compiler模块),原因是jdk.compiler未向未命名模块导出该包。

调试发现getOwnModule返回未命名模块,而JDK源码中implAddOpens对未命名模块直接返回,不执行打开操作。尽管注解处理器项目已添加module-info.java声明模块依赖,问题仍未解决。

此前尝试的两种方案均无效:

  • 移除annotationProcessorPaths中的自定义处理器:导致自定义注解处理器完全不生效
  • 移除注解处理器的module-info.java,改用JVM参数--add-opens打开相关包并添加<fork>true</fork>:仍出现访问错误,且保留Lombok时自定义处理器会被跳过

正确解决方案步骤

1. 确保注解处理器项目为模块化结构(保留module-info.java)

在注解处理器的module-info.java中,明确声明对jdk.compiler的依赖,并通过provides语句暴露处理器实现:

module org.example.async.log.client.annotation {
    requires jdk.compiler;
    requires lombok; // 若依赖Lombok则添加
    exports org.example.async.log.client.annotation;
    provides javax.annotation.processing.Processor with org.example.async.log.client.annotation.AsyncLogProcessor;
}

核心是provides语句,确保编译器能识别到模块化的注解处理器,避免处理器落入未命名模块。

2. 在使用方项目中正确配置Maven编译器插件

必须将自定义处理器作为模块化依赖加入annotationProcessorPaths,同时给指定模块添加--add-opens权限,而非未命名模块:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <release>21</release>
                <fork>true</fork>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.example</groupId>
                        <artifactId>async-log-client-annotation</artifactId>
                        <version>1.0.0</version>
                    </path>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>1.18.30</version>
                    </path>
                </annotationProcessorPaths>
                <compilerArgs>
                    <!-- 给自定义处理器模块打开jdk.compiler的内部包权限 -->
                    <arg>--add-opens=jdk.compiler/com.sun.tools.javac.api=org.example.async.log.client.annotation</arg>
                    <arg>--add-opens=jdk.compiler/com.sun.tools.javac.processing=org.example.async.log.client.annotation</arg>
                    <!-- 按需添加其他需要打开的包 -->
                    <!-- 强制Lombok包含自定义处理器 -->
                    <arg>-Alombok.processors.include=org.example.async.log.client.annotation.AsyncLogProcessor</arg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

这里的关键是--add-opens参数要指定自定义处理器的模块名,JDK会允许给明确的模块打开内部包权限,而非未命名模块。

3. 验证打包后的模块化JAR

执行jar tf target/async-log-client-annotation-1.0.0.jar,确认根目录下存在module-info.class,确保处理器JAR是模块化的。

原方案失败原因

  • 方案1移除annotationProcessorPaths:编译器无法定位自定义处理器,直接导致失效
  • 方案2移除module-info.java:处理器回到未命名模块,JDK的implAddOpens不对未命名模块执行打开操作;同时--add-opens给未命名模块开权限在JDK21中限制更严格,加上Lombok的处理器优先级逻辑,导致自定义处理器被跳过

内容的提问来源于stack exchange,提问作者Photon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:33:19