Lombok 对 jdk.compiler 的内部包的访问与 Java-16 不兼容
Lombok's access to jdk.compiler's internal packages incompatible with Java-16
只需将我的一个项目从 Java-15 升级到 16(使用最新版本 here)。在编译使用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>
有没有人能够解决或摆脱这个问题?
Edit: 提供的 link 与 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 supports JDK 16 out of the box.
在同一个线程中,维护者之一也 writes:
We have some less well known loopholes we can use to bridge a few gaps. We'll start work on gradle and maven plugins in the mean time, which will be a long-term fix.
原文:
您在最新 JDK-16 版本中看到的异常是由于 JEP 396: Strongly Encapsulate JDK Internals by Default。 Lombok 正在使用反射访问内部 JDK API,在以前的 Java 版本中这会导致警告消息,现在会导致硬错误。
一般来说,当 运行 java 时,通过将 --add-opens=<module>/<package>=<accessing module>
指令作为 VM 参数传递 运行 时,可以显式打开内部 JDK 包进行反射] java
。在这种情况下,这些指令需要传递给调用 javac
时运行的 java
进程。这可以通过在传递给 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 文档,在使用 <compilerArgs>
:
时似乎随时都需要将 fork
设置为 true
https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#compilerArgs
<compilerArgs>
Sets the arguments to be passed to the compiler if fork
is set to true
.
帮助 Gradle 可能参与此主题的用户。
对于使用 Gradle
的用户,要正确配置 Lombok,请在 build.gradle
文件中使用 compileOnly
和 annotationProcessor
。
// Lombok
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
如果您也在那里使用 Lombok,test dependencies
也是如此:
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
此外,如果您想明确生成针对 JDK 16
的字节码,请使用:
sourceCompatibility = '16'
targetCompatibility = '16'
来源:
Set up Lombok and Gradle
Gradle sourceCompatibility and targetCompatibility
您需要更改您的sdk版本。
如果您使用 IntelliJ IDEA 文件 > 项目结构和左侧的 select 'project' 选项卡。项目 SDK 应该是 1.8 或您在项目中使用的任何版本。 Java 版本 16.0.1 不支持访问此版本的 lombok
将 lombok 版本升级到 1.18.20
为我修复了它。所以,如果你可以升级 lombok,我建议你这样做。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
如果你使用macos搭配jenv,出现这个问题的原因是环境变量JAVA_HOME没有激活,只需执行以下操作:
jenv enable-plugin export
然后重新打开终端会话并键入 echo $JAVA_HOME
我发现的是设置我的 JAVA_HOME 变量。如果你不知道那是什么,你可以运行这个命令来找到它。
java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home'
并将您的 RC 文件中的值设置为 JAVA_HOME。
对于那些使用 Java 11 或任何不同于最新版本的人,请记住 IntelliJ 可以使用其自己的 Maven 版本挂接到 JDK 16/17,从而导致从 IntelliJ 终端执行 mvn clean install
时出现上述错误。
要检查实际使用的 JDK,请在终端中输入 mvn --version
,您可能会像我一样得到惊喜(我什至不知道我有 JDK 17) :
Maven home: /usr/local/Cellar/maven/3.8.4/libexec
Java version: 17.0.1, vendor: Homebrew, runtime: /usr/local/Cellar/openjdk/17.0.1_1/libexec/openjdk.jdk/Contents/Home
Default locale: en_BG, platform encoding: UTF-8
OS name: "mac os x", version: "11.3.1", arch: "x86_64", family: "mac"
同时,我在检查java --version
时得到Java11。
这里的解决方案是通过右侧 Maven 选项卡中的 Maven 目标按钮执行 mvn clean install
:
它正确地使用了 JDK 11,这也可以通过 mvn --version
来验证。
只需将我的一个项目从 Java-15 升级到 16(使用最新版本 here)。在编译使用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>
有没有人能够解决或摆脱这个问题?
Edit:
<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 supports JDK 16 out of the box.
在同一个线程中,维护者之一也 writes:
We have some less well known loopholes we can use to bridge a few gaps. We'll start work on gradle and maven plugins in the mean time, which will be a long-term fix.
原文:
您在最新 JDK-16 版本中看到的异常是由于 JEP 396: Strongly Encapsulate JDK Internals by Default。 Lombok 正在使用反射访问内部 JDK API,在以前的 Java 版本中这会导致警告消息,现在会导致硬错误。
一般来说,当 运行 java 时,通过将 --add-opens=<module>/<package>=<accessing module>
指令作为 VM 参数传递 运行 时,可以显式打开内部 JDK 包进行反射] java
。在这种情况下,这些指令需要传递给调用 javac
时运行的 java
进程。这可以通过在传递给 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 文档,在使用 <compilerArgs>
:
fork
设置为 true
https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#compilerArgs
<compilerArgs>
Sets the arguments to be passed to the compiler iffork
is set totrue
.
帮助 Gradle 可能参与此主题的用户。
对于使用 Gradle
的用户,要正确配置 Lombok,请在 build.gradle
文件中使用 compileOnly
和 annotationProcessor
。
// Lombok
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
如果您也在那里使用 Lombok,test dependencies
也是如此:
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
此外,如果您想明确生成针对 JDK 16
的字节码,请使用:
sourceCompatibility = '16'
targetCompatibility = '16'
来源:
Set up Lombok and Gradle
Gradle sourceCompatibility and targetCompatibility
您需要更改您的sdk版本。
如果您使用 IntelliJ IDEA 文件 > 项目结构和左侧的 select 'project' 选项卡。项目 SDK 应该是 1.8 或您在项目中使用的任何版本。 Java 版本 16.0.1 不支持访问此版本的 lombok
将 lombok 版本升级到 1.18.20
为我修复了它。所以,如果你可以升级 lombok,我建议你这样做。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
如果你使用macos搭配jenv,出现这个问题的原因是环境变量JAVA_HOME没有激活,只需执行以下操作:
jenv enable-plugin export
然后重新打开终端会话并键入 echo $JAVA_HOME
我发现的是设置我的 JAVA_HOME 变量。如果你不知道那是什么,你可以运行这个命令来找到它。
java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home'
并将您的 RC 文件中的值设置为 JAVA_HOME。
对于那些使用 Java 11 或任何不同于最新版本的人,请记住 IntelliJ 可以使用其自己的 Maven 版本挂接到 JDK 16/17,从而导致从 IntelliJ 终端执行 mvn clean install
时出现上述错误。
要检查实际使用的 JDK,请在终端中输入 mvn --version
,您可能会像我一样得到惊喜(我什至不知道我有 JDK 17) :
Maven home: /usr/local/Cellar/maven/3.8.4/libexec
Java version: 17.0.1, vendor: Homebrew, runtime: /usr/local/Cellar/openjdk/17.0.1_1/libexec/openjdk.jdk/Contents/Home
Default locale: en_BG, platform encoding: UTF-8
OS name: "mac os x", version: "11.3.1", arch: "x86_64", family: "mac"
同时,我在检查java --version
时得到Java11。
这里的解决方案是通过右侧 Maven 选项卡中的 Maven 目标按钮执行 mvn clean install
:
它正确地使用了 JDK 11,这也可以通过 mvn --version
来验证。