Kotlin中无法识别的属性名称MODULE:错误解析

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

遭遇幽灵:什么是"unrecognized Attribute name MODULE"?

\n

你是否见过一种充满神秘感的错误?想象一下:你正在用现代Kotlin编写代码,一切运行流畅,Gradle正常运转,突然——砰!——日志中出现了类似这样的内容:

\n
unrecognized Attribute name MODULE (class com.sun.tools.javac.util.SharedNameTable$NameImpl)
\n

你去谷歌搜索,发现Stack Overflow上有成千上万的浏览量,然后意识到:这不仅仅是一个bug。这是——兼容性错误——发生在不同世界之间。在Java和Kotlin之间。在旧的构建系统和新的模块化世界之间。

\n

在这篇文章中,我们不仅会提供解决方案。我们还将深入Java编译器的内部,解析什么是SharedNameTable,为什么JVM会对MODULE这个词报错,以及这与你的Kotlin项目有何关联。剧透:罪魁祸首不是Kotlin,而是旧的Gradle和Java 9+。

\n\n

简要说明:如何修复(给急性子的人)

\n

如果你需要紧急修复构建——这里有三种可行方法。根据情况选择:

\n
    \n
  • 方法1(推荐):将Gradle升级到7.0+版本,并将Kotlin Gradle Plugin升级到1.5+。这将永久解决问题。
  • \n
  • 方法2(快速解决方案):在build.gradle.kts中显式指定JVM target:
  • \n
\n
kotlin {\n    jvmToolchain(11) // 或者8,如果你想要旧版兼容性\n}
\n
    \n
  • 方法3(临时方案):为编译器添加标志:
  • \n
\n
tasks.withType<KotlinCompile> {\n    kotlinOptions {\n        jvmTarget = "1.8"\n    }\n}
\n

但如果你想理解为什么这样有效——请继续阅读。我们将深入Java编译器的深处。

\n\n

幕后揭秘:什么是com.sun.tools.javac.util.SharedNameTable$NameImpl?

\n

让我们逐部分解析这个可怕的字符串。这不仅仅是一串随机的单词——它指向Java Development Kit (JDK)内的一个特定类。

\n
    \n
  • com.sun.tools.javac——内部Java编译器(javac)的包。没错,就是那个将.java转换成.class的编译器。
  • \n
  • util.SharedNameTable——一个工具类,用于在字符串池中存储名称(变量、方法、类),以进行优化。这是一个缓存,避免创建数百万个相同的字符串。
  • \n
  • $NameImpl——一个内部类,表示具体的名称。当编译器遇到module这个词时,它会创建一个NameImpl对象。
  • \n
\n

现在最有趣的部分来了:当javac在class文件中遇到MODULE属性,但不知道如何处理时,就会发生错误。如果你使用的是旧编译器(< Java 9),或者反过来,使用新编译器但旧的class文件格式,就会发生这种情况。

\n\n

为什么MODULE是一个特殊词?

\n

从Java 9开始,语言中引入了模块系统(Project Jigsaw)。关键字module成为保留字。在class文件中出现了新的属性,如Module、ModulePackages、ModuleMainClass等。

\n

当Kotlin编译器生成字节码时,如果你的JVM target设置为9+,它可能会偶然(或有意)添加这个属性。而旧的Gradle或Maven,使用过时的javac版本,无法理解这些属性。错误由此产生。

\n\n

实际示例:Kotlin + Gradle + Java 11

\n

想象一个基于Gradle的简单Kotlin项目。以下是build.gradle.kts文件:

\n
plugins {\n    kotlin("jvm") version                

博客

书籍推荐