Lombok's access to jdk.compiler's internal packages incompatible with Java-16

JavaMavenLombokIncompatibilityJava 16

Java Problem Overview


Simply upgrading one of my projects from Java-15 to 16 (using the latest build here). On compiling the project which uses lombok such as:

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

I am kind of stuck with the stack trace

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)

Now, at least as I thought I knew a hack to get this resolved, but even on trying the following configuration on 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>

Has anyone been able to resolve or get away with this?

Edit: The link, provided by Jorn in comments, does relate to the same problem on GitHub, but the solutions proposed still doesn't really work. Such that I have added the following args as well:

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

Java Solutions


Solution 1 - Java

Update:

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

In the same thread, one of the maintainers also 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.


Original:

The exception you are seeing with the latest JDK-16 build is because of JEP 396: Strongly Encapsulate JDK Internals by Default. Lombok is accessing an internal JDK API with reflection, and where in previous Java versions this would result in a warning message, it now results in a hard error.

In general, it is possible to explicitly open internal JDK packages for reflection when running java by passing --add-opens=<module>/<package>=<accessing module> directives as VM arguments when running java. In this case these directives would need to be passed to the java process that runs when invoking javac. This can be done by prefixing the option passed to javac with -J, which will instead pass it to the underlying JVM.

Using Maven, I was able to make it work with the following compiler plugin config:

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

Where the needed options are passed using <compilerArgs> elements in the configuration.

Note that I added -J in front of the options in order to pass them to the JVM running javac, instead of javac options.

On top of the --add-opens directives listed in the question, an additional:

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

was also needed.

<fork>true</fork> was also needed since otherwise the -J options were being ignored (judging from the output of mvn clean install -X). Looking at the Maven docs, setting fork to true seems to be needed any time when using <compilerArgs>:

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.

Solution 2 - Java

Upgrading lombok version to 1.18.20 fixed it for me. So, if you can upgrade lombok, I'd recommend doing so.

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

Solution 3 - Java

For those of you using Java 11 or any different one from the newest versions, keep in mind that IntelliJ can use its own Maven version hooked to JDK 16/17, thereby causing the error above when doing mvn clean install from the IntelliJ terminal.

To check the actual JDK used, type mvn --version in the terminal, and you might get a surprise like I did (I did not even know I had 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"

At the same time, I get Java 11 when checking java --version.

The solution here was to execute mvn clean install via the Maven Goal button in the Maven tab to the right:

enter image description here

It correctly used the JDK 11, which can also be verified via mvn --version.

Solution 4 - Java

To help Gradle users that perhaps get in this topic.

For those using Gradle, to configure Lombok properly, use compileOnly and annotationProcessor in the build.gradle file.

// Lombok
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'

The same for test dependencies if you are using Lombok there too:

testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'

Also, if you would like to explicitly generate your bytecodes targeting JDK 16, use:

sourceCompatibility = '16'
targetCompatibility = '16'

Source:
Set up Lombok and Gradle
Gradle sourceCompatibility and targetCompatibility

Solution 5 - Java

if you use macos with jenv, The reason for this problem is that the environment variable JAVA_HOME is not active, Simply do the following:

jenv enable-plugin export

then reopen a terminal session and type echo $JAVA_HOME

Solution 6 - Java

You need to change your sdk version.

If you use IntelliJ IDEA File>Project Structure and select 'project' tab from the left side. Project SDK should be 1.8 or whatever you use in the project. Java version 16.0.1 doesnt support for access this version of lombok

Solution 7 - Java

What I found was to set my JAVA_HOME variable. If you don't know what that is you can run this command to find it.

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

And set the value in your RC file to JAVA_HOME.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNamanView Question on Stackoverflow
Solution 1 - JavaJorn VerneeView Answer on Stackoverflow
Solution 2 - JavapratyushView Answer on Stackoverflow
Solution 3 - JavaPetar BivolarskiView Answer on Stackoverflow
Solution 4 - JavaJuliano MacedoView Answer on Stackoverflow
Solution 5 - JavaBrookView Answer on Stackoverflow
Solution 6 - JavaA. BerkView Answer on Stackoverflow
Solution 7 - Javareka18View Answer on Stackoverflow