Encuentro con un fantasma: ¿qué es "unrecognized Attribute name MODULE"?
\n¿Alguna vez has visto un error que huele a misticismo? Imagina: estás escribiendo en Kotlin moderno, todo vuela, Gradle zumba, y de repente — ¡bam! — en los registros aparece algo como:
\nunrecognized Attribute name MODULE (class com.sun.tools.javac.util.SharedNameTable$NameImpl)\nBuscas en Google, encuentras Stack Overflow con miles de visitas, y te das cuenta: esto no es solo un bug. Es un error de compatibilidad entre mundos. Entre Java y Kotlin. Entre el antiguo sistema de compilación y el nuevo mundo modular.
\nEn este artículo no solo daremos la solución. Nos asomaremos bajo el capó del compilador de Java, analizaremos qué es SharedNameTable, por qué la JVM se queja de la palabra MODULE, y cómo se relaciona esto con tu proyecto Kotlin. Spoiler: el culpable no es Kotlin, sino el viejo Gradle y Java 9+.
En resumen: cómo solucionarlo (para los impacientes)
\nSi necesitas arreglar la compilación urgentemente — aquí tienes tres formas funcionales. Elige según tu situación:
\n- \n
- Forma 1 (recomendada): Actualiza Gradle a la versión 7.0+ y el Plugin de Gradle para Kotlin a 1.5+. Esto solucionará el problema para siempre. \n
- Forma 2 (solución rápida): Especifica explícitamente el JVM target en
build.gradle.kts: \n
kotlin {\n jvmToolchain(11) // o 8, si quieres compatibilidad antigua\n}\n- \n
- Forma 3 (parche): Añade la bandera al compilador: \n
tasks.withType<KotlinCompile> {\n kotlinOptions {\n jvmTarget = "1.8"\n }\n}\nPero si quieres entender por qué funciona esto — sigue leyendo. Nos sumergiremos en las profundidades del compilador de Java.
\n\nBajo el capó: ¿qué es com.sun.tools.javac.util.SharedNameTable$NameImpl?
\nAnalicemos esta aterradora cadena por partes. No es solo un conjunto aleatorio de palabras — es una referencia a una clase específica dentro del Java Development Kit (JDK).
\n- \n
com.sun.tools.javac— el paquete interno del compilador de Java (javac). Sí, ese mismo que convierte.javaen.class. \n util.SharedNameTable— una clase de utilidad que almacena nombres (de variables, métodos, clases) en un pool de cadenas para optimización. Es un caché para no crear un millón de cadenas iguales. \n $NameImpl— una clase interna que representa un nombre específico. Cuando el compilador encuentra la palabramodule, crea un objetoNameImpl. \n
Y ahora lo más interesante: el error ocurre cuando javac se topa con el atributo MODULE en un archivo class, pero no sabe qué hacer con él. Esto sucede si usas un compilador antiguo (< Java 9) o, por el contrario, un compilador nuevo pero con un formato de archivo class antiguo.
\n\n¿Por qué MODULE es una palabra especial?
\nA partir de Java 9, apareció en el lenguaje el sistema de módulos (Project Jigsaw). La palabra clave module se volvió reservada. En los archivos class aparecieron nuevos atributos como Module, ModulePackages, ModuleMainClass, etc.
Cuando el compilador de Kotlin genera bytecode, puede añadir (accidental o intencionadamente) este atributo si tu JVM target está configurado en 9+. Y un Gradle o Maven antiguo, al usar una versión obsoleta de javac, no entiende estos atributos. De ahí el error.
\n\nEjemplo real: Kotlin + Gradle + Java 11
\nImagina un proyecto Kotlin simple en Gradle. Aquí está el archivo build.gradle.kts:
plugins {\n kotlin("jvm") version