Lombok访问jdk.compiler的内部包与Java-16不兼容
只需将我的一个项目从 Java-15 升级到 16(使用此处的最新版本)。在编译使用 lombok 的项目时,例如:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
我有点被堆栈跟踪卡住了
Caused by: java.lang.IllegalAccessError: class lombok.javac.apt.LombokProcessor (in unnamed module @0x4e670245) cannot access class com.sun.tools.javac.processing.JavacProcessingEnvironment (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.processing to unnamed module @0x4e670245
at lombok.javac.apt.LombokProcessor.getJavacProcessingEnvironment (LombokProcessor.java:433)
at lombok.javac.apt.LombokProcessor.init (LombokProcessor.java:92)
at lombok.core.AnnotationProcessor$JavacDescriptor.want (AnnotationProcessor.java:160)
at lombok.core.AnnotationProcessor.init (AnnotationProcessor.java:213)
at lombok.launch.AnnotationProcessorHider$AnnotationProcessor.init (AnnotationProcessor.java:64)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$ProcessorState.<init> (JavacProcessingEnvironment.java:702)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors$ProcessorStateIterator.next (JavacProcessingEnvironment.java:829)
现在,至少我认为我知道解决这个问题的技巧,但即使在尝试以下配置时 maven-compiler-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>16</source>
<target>16</target>
<!-- <release>16</release>-->
<compilerArgs>
<arg>--enable-preview</arg>
<arg>-Xlint:all</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
</compilerArgs>
<!--for unmappable characters in classes-->
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
<!--for lombok annotations to resolve-->
<!--contradictory to maven, intelliJ fails with this-->
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
有没有人能够解决或摆脱这个?
编辑: Jorn 在评论中提供的链接确实与 GitHub 上的相同问题有关,但提出的解决方案仍然不起作用。这样我也添加了以下参数:
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
回答
更新:
Lombok v1.18.20 支持 JDK 16 开箱即用。
在同一线程中,其中一位维护者还写道:
我们有一些鲜为人知的漏洞,可以用来弥补一些差距。同时,我们将开始研究 gradle 和 maven 插件,这将是一个长期修复。
您在最新的 JDK-16 版本中看到的例外是因为JEP 396: Strongly Encapsulate JDK Internals by Default。Lombok 正在使用反射访问内部 JDK API,在以前的 Java 版本中,这会导致警告消息,现在会导致硬错误。
通常,通过--add-opens=<module>/<package>=<accessing module>在运行java. 在这种情况下,这些指令需要传递给java调用javac. 这可以通过前缀传递给选项来完成javac用-J,这将代替它传递给底层的JVM。
使用 Maven,我能够使用以下编译器插件配置使其工作:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>16</source>
<target>16</target>
<!-- <release>16</release>-->
<fork>true</fork>
<compilerArgs>
<arg>--enable-preview</arg>
<arg>-Xlint:all</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
<arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED</arg>
</compilerArgs>
<!--for unmappable characters in classes-->
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
<!--for lombok annotations to resolve-->
<!--contradictory to maven, intelliJ fails with this-->
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
使用<compilerArgs>配置中的元素传递所需选项的位置。
请注意,我-J在选项前面添加了为了将它们传递给正在运行的 JVM javac,而不是javac选项。
在--add-opens问题中列出的指令之上,还有一个:
-J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED
也需要。
<fork>true</fork>还需要,因为否则-J选项将被忽略(从 的输出判断mvn clean install -X)。查看 Maven 文档,在使用时似乎随时都需要设置fork为:true<compilerArgs>
https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#compilerArgs
<compilerArgs>如果fork设置为 ,则设置要传递给编译器的参数true。
- It’s funny, how it always escalates the same way. *JDK issues a warning* → “but it still works”, some years later: *JDK produces an error* → “but I can make it work with an option”, yet another years later *hack stops working completely* → “why are they suddenly break compatibility?”
- Yeah, we definitely reached warning fatigue for illegal access warnings. I blame both sides - library authors by continuing to use that, and OpenJDK by not looking for why people requires it. I still don't know of a supported replacement for `java.io.Console.cs`. But the same thing is exposed as shared secret - because some other part of OpenJDK depends on it.