Compatibilidade JVM do Gradle: como integrar Kotlin 1.8 e Java 11

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que seu projeto em Kotlin e Java de repente "quebra"?

\n\n

Você já se deparou com uma situação em que escreve código em Kotlin, usa Java 11 para o código principal, e o Gradle de repente exibe um erro de compatibilidade? Familiar? Este é um dos problemas mais comuns ao configurar projetos multimódulo. Especialmente quando você usa build.gradle.kts (Kotlin DSL) e tenta integrar compileJava com compileKotlin. Neste artigo, vamos analisar como definir corretamente a compatibilidade de alvo JVM para Java 11 e Kotlin 1.8, para que seu projeto seja compilado sem erros. E sim, faremos isso em português, com humor e sem teoria entediante.

\n\n

Se você veio do Stack Overflow, sabe que a pergunta original acumulou milhares de visualizações. Nós a adaptaremos para um formato educacional, para que você não apenas copie a resposta, mas entenda por que o erro ocorre e como evitá-lo no futuro.

\n\n

Problema: quando Java e Kotlin falam línguas diferentes

\n\n

Imagine que Java 11 é um professor rigoroso, que exige que tudo esteja de acordo com o padrão. E Kotlin 1.8 é seu colega criativo, que quer usar novos recursos, mas esquece de avisar o professor. O resultado é um conflito.

\n\n

No Gradle, cada tarefa de compilação (compileJava, compileKotlin) tem seu próprio alvo JVM — a versão do bytecode para a qual o código é compilado. Se eles não coincidirem, você receberá um erro como:

\n\n
Error: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.0, expected version is 1.6.0.\n
\n\n

Ou, pior ainda, uma queda silenciosa de desempenho devido à incompatibilidade do bytecode.

\n\n

Por que isso acontece especificamente no build.gradle.kts?

\n\n

Kotlin DSL (arquivos .gradle.kts) é uma ferramenta poderosa, mas exige a especificação explícita dos parâmetros. Ao contrário do Groovy DSL, onde algumas configurações são "capturadas" automaticamente, no Kotlin DSL você precisa ser preciso. Isso é especialmente verdadeiro para o alvo JVM.

\n\n

Erro típico: você define java.targetCompatibility = JavaVersion.VERSION_11, mas esquece de especificar o mesmo para o Kotlin. Ou vice-versa — configura compileKotlin, mas compileJava permanece no Java 8.

\n\n

Solução correta: alvo JVM unificado para Java e Kotlin

\n\n

Para evitar erros, você precisa definir explicitamente o alvo JVM para ambas as tarefas. Veja como fazer isso no build.gradle.kts:

\n\n

Passo 1. Configuração do Java (compileJava)

\n\n

Adicione no bloco java {} ou em tasks.withType<JavaCompile>():

\n\n
java {\n    sourceCompatibility = JavaVersion.VERSION_11\n    targetCompatibility = JavaVersion.VERSION_11\n}\n\ntasks.withType<JavaCompile>() {\n    options.encoding = "UTF-8"\n    options.compilerArgs.add("-parameters")\n}\n
\n\n

Observe: sourceCompatibility e targetCompatibility devem ser iguais. Se você escreve código em Java 11, o bytecode também deve ser Java 11.

\n\n

Passo 2. Configuração do Kotlin (compileKotlin)

\n\n

Agora, o mais importante — definir o alvo JVM para o Kotlin. Isso é feito através do bloco kotlin {} ou através de tasks.withType<KotlinCompile>():

\n\n
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\ntasks.withType<KotlinCompile>() {\n    kotlinOptions {\n        jvmTarget = "11"  // Atenção: isso é uma string, não JavaVersion!\n        apiVersion = "1.8"\n        languageVersion = "1.8"\n    }\n}\n
\n\n

Por que jvmTarget é uma string? Porque o Kotlin espera exatamente uma representação textual da versão (por exemplo, "1.8", "11", "17"). Se você tentar passar JavaVersion.VERSION_11, o compilador exibirá um erro.

\n\n

Exemplo completo do build.gr

Blogs

Book Recommendations