Begegnung mit einem Geist: Was ist "unrecognized Attribute name MODULE"?
\nHaben Sie jemals einen Fehler gesehen, der nach Mystik riecht? Stellen Sie sich vor: Sie programmieren in modernem Kotlin, alles fliegt, Gradle summt, und plötzlich – bumm! – erscheint in den Logs so etwas wie:
\nunrecognized Attribute name MODULE (class com.sun.tools.javac.util.SharedNameTable$NameImpl)\nSie googeln, finden Stack Overflow mit tausenden Aufrufen und verstehen: Das ist nicht einfach ein Bug. Das ist ein Kompatibilitätsfehler zwischen den Welten. Zwischen Java und Kotlin. Zwischen dem alten Build-System und der neuen Modulwelt.
\nIn diesem Artikel geben wir nicht nur eine Lösung. Wir werfen einen Blick unter die Haube des Java-Compilers, analysieren, was SharedNameTable ist, warum die JVM sich über das Wort MODULE beschwert und wie das mit Ihrem Kotlin-Projekt zusammenhängt. Spoiler: Schuld ist nicht Kotlin, sondern ein altes Gradle und Java 9+.
Kurzfassung: So beheben Sie den Fehler (für Ungeduldige)
\nWenn Sie den Build schnell reparieren müssen – hier sind drei funktionierende Methoden. Wählen Sie je nach Situation:
\n- \n
- Methode 1 (empfohlen): Aktualisieren Sie Gradle auf Version 7.0+ und das Kotlin Gradle Plugin auf 1.5+. Das behebt das Problem dauerhaft. \n
- Methode 2 (schnelle Lösung): Geben Sie explizit das JVM-Target in
build.gradle.ktsan: \n
kotlin {\n jvmToolchain(11) // oder 8, wenn Sie alte Kompatibilität wünschen\n}\n- \n
- Methode 3 (Notlösung): Fügen Sie dem Compiler ein Flag hinzu: \n
tasks.withType<KotlinCompile> {\n kotlinOptions {\n jvmTarget = "1.8"\n }\n}\nWenn Sie jedoch verstehen möchten, warum das funktioniert – lesen Sie weiter. Wir tauchen in die Tiefen des Java-Compilers ein.
\n\nUnter der Haube: Was ist com.sun.tools.javac.util.SharedNameTable$NameImpl?
\nLassen Sie uns diese gruselige Zeile Stück für Stück zerlegen. Es ist nicht nur eine zufällige Wortfolge – es ist ein Verweis auf eine bestimmte Klasse innerhalb des Java Development Kit (JDK).
\n- \n
com.sun.tools.javac– das Paket des internen Java-Compilers (javac). Ja, desjenigen, der.javain.classumwandelt. \n util.SharedNameTable– eine Hilfsklasse, die Namen (von Variablen, Methoden, Klassen) in einem String-Pool zur Optimierung speichert. Es ist ein Cache, um nicht eine Million identischer Strings zu erstellen. \n $NameImpl– eine innere Klasse, die einen bestimmten Namen repräsentiert. Wenn der Compiler auf das Wortmodulestößt, erstellt er einNameImpl-Objekt. \n
Und jetzt das Interessanteste: Der Fehler tritt auf, wenn javac auf das Attribut MODULE in einer Class-Datei stößt, aber nicht weiß, was damit anzufangen ist. Dies passiert, wenn Sie einen alten Compiler (< Java 9) oder umgekehrt einen neuen Compiler, aber ein altes Class-Datei-Format verwenden.
\n\nWarum ist MODULE ein besonderes Wort?
\nAb Java 9 wurde in der Sprache das Modulsystem (Project Jigsaw) eingeführt. Das Schlüsselwort module wurde reserviert. In Class-Dateien kamen neue Attribute wie Module, ModulePackages, ModuleMainClass usw. hinzu.
Wenn der Kotlin-Compiler Bytecode generiert, kann er dieses Attribut versehentlich (oder absichtlich) hinzufügen, wenn Ihr JVM-Target auf 9+ gesetzt ist. Ein altes Gradle oder Maven, das eine veraltete Version von javac verwendet, versteht diese Attribute nicht. Daher der Fehler.
\n\nPraktisches Beispiel: Kotlin + Gradle + Java 11
\nStellen Sie sich ein einfaches Kotlin-Projekt mit Gradle vor. Hier ist die Datei build.gradle.kts:
plugins {\n kotlin("jvm") version