正在开发类似lombok的编译时注解处理器程序,但由于jdk9+模块化的问题,某些类未导出给未命名模块,导致出现以下类似问题,在此寻求解决方案。
class com.wenqiuhan.tool.enhanno.application.Application (in unnamed module @0x4190bc8a)
cannot access class com.sun.tools.javac.api.JavacTrees (in module jdk.compiler)
because module jdk.compiler does not export com.sun.tools.javac.api to unnamed module @0x4190bc8a
jdk17
+ gradle(kotlin-dsl)
wen-tool-enhanno-annotation 存放注解
wen-tool-enhanno-processor 存放注解处理程序
根据IDEA提示结合网上搜索进行如下配置,解决了爆红的问题
效果:
仍旧是经过一番搜索,得到以下解决方案成功build:
本项目中的模块依赖该注解处理器,成功进行build
将注解处理器和注解模块发布为maven到本地maven仓库后,在其他模块引入,仍旧提示cannot access class com.sun.tools
问题
在引入processor模块时添加一些配置是能解决,但是终归是不太友好的方式,最好是在我这边就能处理而不是让使用者去添加一些额外配置。
(因为编译时注解处理器会在编译时增加字段或方法,所以会写相关的IDEA插件使IDEA识别。如果插件某些功能可以解决这个问题,也可以写插件,但是没有相关思路,有知道的同学可以告诉一下)
看得出来你很想解决这个问题,
我记得maven是可以引入相关jar的,在编译阶段就引用的相关设置,而不需要从IDEA额外配置 java compiler, 反而显得臃肿
这样的话 就不需要额外的添加配置了,
至于,tools.jar 文件,我记得好像是1.8中带的,文中使用的jdk 是 17 ,可以考虑更换jdk 为 1.8
maven配置示例(自行调整为 gradle 配置):
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.8.0_202</version>
<scope>system</scope>
<systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
</dependency>
使用开放性命令行选项来暴露所需的模块和包,在 processor 模块中使用额外的配置,编写自定义的 IntelliJ IDEA 插件来处理该问题,编写自定义的 IntelliJ IDEA 插件,可以通过使用 IDEA 提供的 API 来解析和处理需要的注解,在编译时对模块化问题做出相应的处理
cannot access class jdk.internal.misc.Unsafe(java9的模块概念)
现成的,可以参考下
使用的是Gradle或Maven等构建工具,可以在构建脚本中添加相应的配置,以确保编译器使用正确的模块。例如,在Gradle中,可以添加以下配置:
tasks.withType(JavaCompile) {
options.compilerArgs.add("--add-modules java.compiler")
}
在引入模块时,添加配置
在编译时,在构建脚本中将相应的模块配置进去
基于bing、GPT部分内容和本人思考总结:
这个问题可能是由于JDK 9及以上版本中的模块化特性导致的。在这些版本中,一些类和API的可访问性发生了变化,可能导致注解处理器中的某些类无法使用。
为了解决这个问题,您可以尝试以下方法:
在注解处理器的模块描述文件中,将需要使用的类所在的模块添加到requires语句中,以明确指定依赖关系。例如:
java
复制代码
requires com.sun.tools.javac;
如果无法修改注解处理器的代码,可以尝试使用反射机制来获取需要使用的类。通过反射可以访问模块之间的非公开API。
如果您使用的是第三方库或框架的注解处理器,可以尝试更新到支持JDK 9及以上版本的最新版本,以解决兼容性问题。
请注意,具体解决方法可能因您的代码和项目设置而异。建议您仔细查阅相关文档,并进一步调查和了解问题的具体细节以找到解决方案。
问题描述表明您遇到了在 JDK 9+ 中由于模块化导致的编译时注解处理器无法访问某些类的问题。这是由于 JDK 9 引入了模块系统,它导致某些类无法直接访问,因为模块默认情况下不会导出所有的包。您已经尝试过一些配置方式,但仍在寻找一个更优雅的解决方案,让开发者无需添加额外配置即可正常使用注解处理器。
在 JDK 9+ 中,模块系统允许您通过模块信息文件 (module-info.java) 明确声明模块的依赖关系和导出包,以便其他模块可以访问。要解决您遇到的问题,您可以尝试以下方法:
1.明确声明注解处理器所需的模块依赖关系和导出的包:
在注解处理器模块(wen-tool-enhanno-processor)的 module-info.java 文件中,添加所需的模块依赖关系和导出的包,例如:
module wen.tool.enhanno.processor {
requires jdk.compiler;
exports com.wenqiuhan.tool.enhanno.application; // 假设这个包是需要导出的
}
这样做将明确告知编译器,该模块依赖于 jdk.compiler 模块,并且导出 com.wenqiuhan.tool.enhanno.application 包供其他模块访问。
2.使用 SPI(Service Provider Interface)方式:
如果您的注解处理器需要和其他模块进行交互,可以考虑使用 Java 的 SPI 机制。SPI 允许您在注解处理器模块中定义服务接口,并在其他模块中提供实现。这样,其他模块就可以通过 SPI 加载注解处理器,而无需显式依赖注解处理器模块。
在您的注解处理器模块中,定义服务接口:
// 定义一个服务接口,例如:
public interface MyAnnotationProcessor {
// 定义需要执行的处理方法
void processAnnotations();
}
3.然后在注解处理器模块的 module-info.java 中声明服务提供者:
module wen.tool.enhanno.processor {
requires jdk.compiler;
exports com.wenqiuhan.tool.enhanno.application;
// 声明服务提供者
provides com.wenqiuhan.tool.enhanno.processor.MyAnnotationProcessor
with com.wenqiuhan.tool.enhanno.application.Application;
}
4.在其他模块中,您可以通过 SPI 机制来加载注解处理器:
import com.wenqiuhan.tool.enhanno.processor.MyAnnotationProcessor;
// 使用 ServiceLoader 加载注解处理器
ServiceLoader<MyAnnotationProcessor> processors =
ServiceLoader.load(MyAnnotationProcessor.class);
for (MyAnnotationProcessor processor : processors) {
processor.processAnnotations();
}
通过 SPI 机制,其他模块无需显式依赖 wen.tool.enhanno.processor 模块,而是在运行时动态加载了注解处理器的实现。
如果您在使用JDK9+时遇到了注解处理器无法访问"com.sun.tools.javac"类的问题,可能是由于JDK9引入了模块化的概念导致的。在模块化中,一些内部的Java编译器类被标记为不可访问。
为了解决这个问题,您可以使用--add-opens
选项来解决无法访问问题。具体步骤如下:
打开您的构建工具(如Maven或Gradle)的配置文件(pom.xml或build.gradle)。
根据您正在使用的构建工具,找到相关配置项用于编译Java代码时的选项设置。
添加--add-opens
选项并指定被访问的模块和被访问的包。例如,对于com.sun.tools.javac
类,您可以添加以下配置:
```
--add-opens java.base/jdk.compiler=com.sun.tools.javac
```
根据您的具体情况,您可能还需要调整其他配置项以适应模块化环境。如果问题仍然存在,建议查阅相关文档和参考资料以获得更详细的解决方法。