【问题标题】:Lombok's access to jdk.compiler's internal packages incompatible with Java-16Lombok 访问 jdk.compiler 的内部包与 Java-16 不兼容
【发布时间】:2021-03-30 11:37:19
【问题描述】:

只需将我的一个项目从 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>

有没有人能够解决或摆脱这个问题?

编辑Jorn in comments 提供的链接确实与 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>

【问题讨论】:

  • 看起来还有一个未解决的问题:github.com/rzwitserloot/lombok/issues/2681 似乎需要超过 1 个附加打开。
  • 查看 maven -X 输出,在运行注释处理器时,它没有将所需的标志添加到命令行。 (请注意,您还需要在标志前面使用-J,以便将其传递给 javac 进程本身)。如果我采用 mavens 命令,并手动将缺少的 -J--add-opens 添加到它,它就可以工作。
  • 好吧,既然问题现在已经结束,我将在此处发布:在将&lt;fork&gt;true&lt;/fork&gt; 添加到编译器插件配置并添加一个缺少的-J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED 后,能够使其工作。跨度>
  • 我认为不包含确切错误的日志是使用 fork=true 的结果。手动运行 javac 时,我看到了更清晰的异常。 maven 文档提示需要 fork=true:maven.apache.org/plugins/maven-compiler-plugin/… "&lt;compilerArgs&gt; 如果fork 设置为true,则设置要传递给编译器的参数"。如果问题被重新打开,我也会在这里发布我使用的配置。
  • @JornVernee 问题重新打开

标签: java maven lombok incompatibility java-16


【解决方案1】:

更新

Lombok v1.18.20 supports JDK 16 out of the box.

在同一线程中,其中一位维护者还writes

我们有一些鲜为人知的漏洞可以用来弥补一些差距。同时,我们将开始研究 gradle 和 maven 插件,这将是一个长期的修复。


原创

您在最新的 JDK-16 构建中看到的异常是因为 JEP 396: Strongly Encapsulate JDK Internals by Default。 Lombok 正在使用反射访问内部 JDK API,在以前的 Java 版本中,这会导致警告消息,现在会导致硬错误。

通常,在运行java 时,通过将--add-opens=&lt;module&gt;/&lt;package&gt;=&lt;accessing module&gt; 指令作为VM 参数传递,可以在运行java 时显式打开内部JDK 包进行反射。在这种情况下,这些指令需要传递给在调用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>

在配置中使用&lt;compilerArgs&gt; 元素传递所需的选项。

请注意,我在选项前面添加了-J,以便将它们传递给运行javac 的JVM,而不是javac 选项。

除了问题中列出的--add-opens 指令之外,还有一个:

-J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED

也是需要的。

&lt;fork&gt;true&lt;/fork&gt; 也是需要的,否则-J 选项将被忽略(从mvn clean install -X 的输出判断)。查看 Maven 文档,在使用 &lt;compilerArgs&gt; 时似乎随时需要将 fork 设置为 true

https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#compilerArgs

&lt;compilerArgs&gt; 如果fork 设置为true,则设置要传递给编译器的参数。

【讨论】:

  • 很快就会增加赏金。但也许可以引导龙目岛应该如何朝着永久修复前进。
  • 向我的团队中的每个人解释为什么要在 maven 配置中添加这么多东西以使 lombok 能够工作是相当复杂的。有 records 让 lombok 过时了,我唯一想念的就是我经常使用的 @Accessor(chain=true)
  • 这很有趣,它总是以同样的方式升级。 JDK 发出警告 → “但它仍然有效”,几年后:JDK 产生错误 → “但我可以使用选项使其工作”,又过了几年后来 hack 完全停止工作 → “为什么他们突然破坏了兼容性?”
  • 是的,我们肯定会因为非法访问警告而达到警告疲劳。我责怪双方——图书馆作者继续使用它,而 OpenJDK 没有寻找人们需要它的原因。我仍然不知道java.io.Console.cs 的支持替代品。但是同样的东西被暴露为共享秘密——因为 OpenJDK 的其他一些部分依赖于它。
  • FWIW,在JDK 17中添加了Console::charset()方法:github.com/openjdk/jdk/pull/3419
【解决方案2】:

将 lombok 版本升级到 1.18.20 为我修复了它。所以,如果你可以升级 lombok,我建议你这样做。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
</dependency>

【讨论】:

  • existing and accepted answer 已经表明了这一点。所以,不知道为什么这应该是一个单独的答案。
  • @Naman 通过看到这个答案更容易理解,直截了当
【解决方案3】:

帮助可能进入该主题的 Gradle 用户。

对于使用Gradle 的用户,要正确配置Lombok,请在build.gradle 文件中使用compileOnlyannotationProcessor

// 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

【讨论】:

    【解决方案4】:

    如果你使用macos和jenv,出现这个问题的原因是环境变量JAVA_HOME没有激活,只需执行以下操作:

    jenv enable-plugin export
    

    然后重新打开一个终端会话并输入echo $JAVA_HOME

    【讨论】:

      【解决方案5】:

      您需要更改您的 sdk 版本。

      如果您使用 IntelliJ IDEA 文件>项目结构并从左侧选择“项目”选项卡。项目 SDK 应该是 1.8 或您在项目中使用的任何版本。 Java 16.0.1 版本不支持访问该版本的lombok

      【讨论】:

        【解决方案6】:

        我发现设置我的 JAVA_HOME 变量。如果你不知道那是什么,你可以运行这个命令来找到它。

        java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home'
        

        并将 RC 文件中的值设置为 JAVA_HOME。

        【讨论】:

          【解决方案7】:

          对于那些使用 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时得到Java 11。

          这里的解决方案是通过右侧 Maven 选项卡中的 Maven Goal 按钮执行 mvn clean install

          它正确使用了JDK 11,也可以通过mvn --version进行验证。

          【讨论】:

            猜你喜欢
            • 2020-11-19
            • 2015-05-30
            • 1970-01-01
            • 2020-07-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-12-19
            • 2015-12-06
            相关资源
            最近更新 更多