El acceso de Lombok a los paquetes internos de jdk.compiler es incompatible con Java-16

11 minutos de lectura

avatar de usuario
Namán

Simplemente actualizando uno de mis proyectos de Java-15 a 16 (usando la última versión aquí). Al compilar el proyecto que usa lombok como:

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

Estoy un poco atascado con el seguimiento de la pila

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)

Ahora, al menos como pensé que conocía un truco para resolver esto, pero incluso al probar la siguiente configuración en 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>

¿Alguien ha podido resolver o salirse con la suya?

Editar: El enlace, proporcionado por Jorn en los comentarios, se relaciona con el mismo problema en GitHub, pero las soluciones propuestas aún no funcionan. De tal manera que también he agregado los siguientes argumentos:

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

  • Parece que también hay un problema abierto en esto: github.com/rzwitserloot/lombok/issues/2681 Parece que se necesitan más de 1 add-opens.

    – Jorn Vernée

    20 de diciembre de 2020 a las 13:38


  • Mirando al experto -X salida, no está agregando los indicadores necesarios a la línea de comandos cuando se ejecuta el procesador de anotaciones. (Tenga en cuenta que también necesita -J delante de la bandera, para que se pase al propio proceso javac). Si tomo el comando mavens y agrego lo que falta -J--add-opens manualmente, funciona.

    – Jorn Vernée

    20 de diciembre de 2020 a las 14:08

  • Bueno, dado que la pregunta ahora está cerrada, publicaré esto aquí: Pude hacer que funcionara después de agregar <fork>true</fork> a la configuración del complemento del compilador y agregar uno más que falta -J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED.

    – Jorn Vernée

    20 dic 2020 a las 14:30


  • Creo que los registros que no contienen el error exacto son una consecuencia del uso de fork=true. Vi una excepción más clara al ejecutar manualmente javac. Los documentos maven fueron una pista sobre la necesidad de fork=true: maven.apache.org/plugins/maven-compiler-plugin/…<compilerArgs> Establece los argumentos que se pasarán al compilador si fork se establece en true“. Publicaré la configuración que usé aquí también si la pregunta se vuelve a abrir.

    – Jorn Vernée

    20 de diciembre de 2020 a las 14:58


  • Pregunta de @JornVernee reabierta

    – Fenio

    20 de diciembre de 2020 a las 15:51

avatar de usuario
Jorn Vernée

Actualizar:

Lombok v1.18.20 admite JDK 16 listo para usar.

En el mismo hilo, uno de los mantenedores también escribe:

Tenemos algunas lagunas menos conocidas que podemos usar para cerrar algunas brechas. Mientras tanto, comenzaremos a trabajar en los complementos de gradle y maven, lo que será una solución a largo plazo.


Original:

La excepción que está viendo con la última versión de JDK-16 se debe a JEP 396: Encapsular fuertemente los componentes internos de JDK de forma predeterminada. Lombok está accediendo a una API JDK interna con reflejo, y donde en versiones anteriores de Java esto resultaba en un mensaje de advertencia, ahora genera un error grave.

En general, es posible abrir explícitamente paquetes JDK internos para que se reflejen cuando se ejecuta java pasando --add-opens=<module>/<package>=<accessing module> directivas como argumentos de VM cuando se ejecuta java. En este caso, estas directivas tendrían que pasar a la java proceso que se ejecuta al invocar javac. Esto se puede hacer anteponiendo la opción pasada a javac con -Jque en su lugar lo pasará a la JVM subyacente.

Usando Maven, pude hacer que funcionara con la siguiente configuración del complemento del compilador:

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

Donde las opciones necesarias se pasan usando <compilerArgs> elementos en la configuración.

Tenga en cuenta que agregué -J delante de las opciones para pasarlas a la JVM que se está ejecutando javacen vez de javac opciones

En la parte superior de la --add-opens directivas enumeradas en la pregunta, un adicional:

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

también se necesitaba.

<fork>true</fork> también era necesario ya que de lo contrario el -J las opciones estaban siendo ignoradas (a juzgar por la salida de mvn clean install -X). Mirando los documentos de Maven, configurando fork a true parece ser necesario en cualquier momento cuando se usa <compilerArgs>:

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

<compilerArgs> Establece los argumentos que se pasarán al compilador si fork se establece en true.

  • Agregaría una recompensa pronto. Pero tal vez con una pista sobre cómo Lombok debería poder avanzar hacia la solución permanente.

    – Namán

    20 de diciembre de 2020 a las 17:59

  • Sería bastante complicado explicarles a todos en mi equipo por qué se agregan tantas cosas a la configuración de maven para que lombok funcione. Existen records que de alguna manera hacen que lombok quede obsoleto, lo único que extrañaría sería @Accessor(chain=true) que uso mucho

    – Eugenio

    20 de diciembre de 2020 a las 20:07

  • Es gracioso, cómo siempre escala de la misma manera. JDK emite una advertencia → “pero todavía funciona”, algunos años después: JDK produce un error → “pero puedo hacerlo funcionar con una opción”, otro año más tarde hack deja de funcionar por completo → “¿Por qué de repente rompen la compatibilidad?”

    – Holger

    21 de diciembre de 2020 a las 11:20

  • Sí, definitivamente alcanzamos la fatiga de advertencia para las advertencias de acceso ilegal. Culpo a ambos lados: los autores de la biblioteca al continuar usando eso, y OpenJDK al no buscar por qué la gente lo requiere. Todavía no conozco un reemplazo compatible para java.io.Console.cs. Pero lo mismo se expone como secreto compartido, porque alguna otra parte de OpenJDK depende de ello.

    – Johannes Kuhn

    22 de diciembre de 2020 a las 1:13


  • FWIW, un Console::charset() El método se agrega en JDK 17: github.com/openjdk/jdk/pull/3419

    – Jorn Vernée

    1 de septiembre de 2021 a las 14:12

Actualización de la versión de lombok a 1.18.20 me lo arregló. Entonces, si puede actualizar lombok, le recomiendo que lo haga.

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

  • La respuesta existente y aceptada ya sugiere eso. Entonces, no estoy seguro de por qué esta debería ser una respuesta separada.

    – Namán

    19 de noviembre de 2021 a las 7:10


  • Sin embargo, @Naman es más fácil de entender al ver esta respuesta, directo al grano

    – Aswzen

    6 de diciembre de 2021 a las 8:15

  • Estaba viendo el mismo error. Actualizar lombok a la última versión funcionó bien con Java 17.

    – Sankalp

    17 de marzo a las 23:10

Para aquellos de ustedes que usan Java 11 o cualquier otro diferente de las versiones más recientes, tenga en cuenta que IntelliJ puede usar su propia versión de Maven conectada a JDK 16/17, lo que provoca el error anterior al hacer mvn clean install desde la terminal IntelliJ.

Para verificar el JDK real utilizado, escriba mvn --version en la terminal, y puede que te lleves una sorpresa como la mía (ni siquiera sabía que tenía 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"

Al mismo tiempo, obtengo Java 11 al verificar java --version.

La solución aquí fue ejecutar mvn clean install a través del botón Maven Goal en la pestaña Maven a la derecha:

ingrese la descripción de la imagen aquí

Usó correctamente el JDK 11, que también se puede verificar a través de mvn --version.

  • ¡Sigo recibiendo el mismo error después de ejecutar desde el botón Maven Goal!

    – Shailesh Kumar

    9 de febrero a las 1:22

avatar de usuario
julian macedo

Para ayudar a los usuarios de Gradle que tal vez entren en este tema.

Para aquellos que usan Gradlepara configurar Lombok correctamente, utilice compileOnly y annotationProcessor en el build.gradle expediente.

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

lo mismo para test dependencies si está usando Lombok allí también:

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

Además, si desea generar explícitamente su orientación de bytecodes JDK 16usar:

sourceCompatibility = '16'
targetCompatibility = '16'

Fuente:
Configurar Lombok y Gradle

Gradle sourceCompatibility y targetCompatibility

si usa macos con jenv, la razón de este problema es que la variable de entorno JAVA_HOME no está activa, simplemente haga lo siguiente:

jenv enable-plugin export

luego vuelva a abrir una sesión de terminal y escriba echo $JAVA_HOME

avatar de usuario
A. Berk

Necesitas cambiar tu versión SDK.

Si usa IntelliJ IDEA Archivo> Estructura del proyecto y selecciona la pestaña ‘proyecto’ en el lado izquierdo. Project SDK debe ser 1.8 o lo que sea que use en el proyecto. La versión de Java 16.0.1 no admite el acceso a esta versión de lombok

avatar de usuario
reka18

Lo que encontré fue configurar mi variable JAVA_HOME. Si no sabe qué es eso, puede ejecutar este comando para encontrarlo.

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

Y establezca el valor en su archivo RC en JAVA_HOME.

¿Ha sido útil esta solución?