Encontro com um fantasma: o que é "unrecognized Attribute name MODULE"?
\nVocê já viu um erro que parece místico? Imagine: você está programando em Kotlin moderno, tudo voa, o Gradle está funcionando, e de repente — bum! — aparece algo assim nos logs:
\nunrecognized Attribute name MODULE (class com.sun.tools.javac.util.SharedNameTable$NameImpl)\nVocê pesquisa no Google, encontra o Stack Overflow com milhares de visualizações e percebe: isso não é apenas um bug. É um erro de compatibilidade entre mundos. Entre Java e Kotlin. Entre o sistema de compilação antigo e o novo mundo modular.
\nNeste artigo, não vamos apenas dar a solução. Vamos olhar sob o capô do compilador Java, entender o que é SharedNameTable, por que a JVM reclama da palavra MODULE e como isso se relaciona com seu projeto Kotlin. Spoiler: a culpa não é do Kotlin, mas do Gradle antigo e do Java 9+.
Resumindo: como corrigir (para os impacientes)
\nSe você precisa corrigir a compilação rapidamente, aqui estão três maneiras. Escolha de acordo com a situação:
\n- \n
- Método 1 (recomendado): Atualize o Gradle para a versão 7.0+ e o Kotlin Gradle Plugin para 1.5+. Isso resolverá o problema permanentemente. \n
- Método 2 (solução rápida): Defina explicitamente o JVM target no
build.gradle.kts: \n
kotlin {\n jvmToolchain(11) // ou 8, se quiser compatibilidade antiga\n}\n- \n
- Método 3 (gambiarra): Adicione uma flag ao compilador: \n
tasks.withType<KotlinCompile> {\n kotlinOptions {\n jvmTarget = "1.8"\n }\n}\nMas se você quiser entender por que isso funciona — continue lendo. Vamos mergulhar nas profundezas do compilador Java.
\n\nSob o capô: o que é com.sun.tools.javac.util.SharedNameTable$NameImpl?
\nVamos analisar essa string assustadora parte por parte. Não é apenas um conjunto aleatório de palavras — é uma referência a uma classe específica dentro do Java Development Kit (JDK).
\n- \n
com.sun.tools.javac— pacote interno do compilador Java (javac). Sim, aquele que transforma.javaem.class. \n util.SharedNameTable— classe utilitária que armazena nomes (de variáveis, métodos, classes) em um pool de strings para otimização. É um cache para não criar um milhão de strings idênticas. \n $NameImpl— classe interna que representa um nome específico. Quando o compilador encontra a palavramodule, ele cria um objetoNameImpl. \n
Agora a parte mais interessante: o erro ocorre quando o javac encontra o atributo MODULE em um arquivo .class, mas não sabe o que fazer com ele. Isso acontece se você estiver usando um compilador antigo (< Java 9) ou, ao contrário, um compilador novo, mas com um formato de arquivo .class antigo.
\n\nPor que MODULE é uma palavra especial?
\nA partir do Java 9, a linguagem ganhou o sistema de módulos (Project Jigsaw). A palavra-chave module tornou-se reservada. Nos arquivos .class, surgiram novos atributos como Module, ModulePackages, ModuleMainClass, etc.
Quando o compilador Kotlin gera bytecode, ele pode acidentalmente (ou intencionalmente) adicionar esse atributo se seu JVM target estiver definido como 9+. E o Gradle ou Maven antigo, usando uma versão desatualizada do javac, não entende esses atributos. Daí o erro.
\n\nExemplo real: Kotlin + Gradle + Java 11
\nImagine um projeto Kotlin simples no Gradle. Aqui está o arquivo build.gradle.kts:
plugins {\n kotlin("jvm") version