Compatibilidad JVM de Gradle: cómo armonizar Kotlin 1.8 y Java 11

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué su proyecto en Kotlin y Java se «desmorona» de repente?

\n\n

¿Alguna vez se ha encontrado en una situación en la que escribe código en Kotlin, usa Java 11 para el código principal, y Gradle de repente muestra un error de compatibilidad? ¿Le suena familiar? Este es uno de los problemas más comunes al configurar proyectos multimódulo. Especialmente cuando usa build.gradle.kts (Kotlin DSL) e intenta armonizar compileJava con compileKotlin. En este artículo, analizaremos cómo establecer correctamente la compatibilidad de destino JVM para Java 11 y Kotlin 1.8, para que su proyecto se compile sin errores. Y sí, lo haremos en español, con humor y sin teoría aburrida.

\n\n

Si vino de Stack Overflow, sabrá que la pregunta original ha acumulado miles de visitas. Lo adaptaremos a un formato educativo para que no solo copie la respuesta, sino que entienda por qué ocurre el error y cómo evitarlo en el futuro.

\n\n

El problema: cuando Java y Kotlin hablan diferentes idiomas

\n\n

Imagine que Java 11 es un profesor estricto que exige que todo esté según el estándar. Y Kotlin 1.8 es su colega creativo que quiere usar las nuevas funciones, pero se olvida de informar al profesor. El resultado es un conflicto.

\n\n

En Gradle, cada tarea de compilación (compileJava, compileKotlin) tiene su propio destino JVM: la versión del bytecode en la que se compila el código. Si no coinciden, obtendrá un error 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

O, lo que es peor, una caída silenciosa del rendimiento debido a la incompatibilidad del bytecode.

\n\n

¿Por qué ocurre esto precisamente en build.gradle.kts?

\n\n

Kotlin DSL (archivos .gradle.kts) es una herramienta potente, pero requiere la especificación explícita de los parámetros. A diferencia de Groovy DSL, donde algunas configuraciones se «toman» automáticamente, en Kotlin DSL debe ser preciso. Esto se aplica especialmente al destino JVM.

\n\n

Error típico: establece java.targetCompatibility = JavaVersion.VERSION_11, pero se olvida de especificar lo mismo para Kotlin. O viceversa: configura compileKotlin, pero compileJava se queda en Java 8.

\n\n

La solución correcta: un destino JVM unificado para Java y Kotlin

\n\n

Para evitar errores, debe establecer explícitamente el destino JVM para ambas tareas. Así es como se hace en build.gradle.kts:

\n\n

Paso 1. Configuración de Java (compileJava)

\n\n

Añada en el bloque java {} o en 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

Tenga en cuenta: sourceCompatibility y targetCompatibility deben ser iguales. Si escribe código en Java 11, el bytecode también debe ser Java 11.

\n\n

Paso 2. Configuración de Kotlin (compileKotlin)

\n\n

Ahora lo más importante: establecer el destino JVM para Kotlin. Esto se hace a través del bloque kotlin {} o mediante tasks.withType<KotlinCompile>():

\n\n
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\ntasks.withType<KotlinCompile>() {\n    kotlinOptions {\n        jvmTarget = "11"  // Atención: esto es una cadena, ¡no JavaVersion!\n        apiVersion = "1.8"\n        languageVersion = "1.8"\n    }\n}\n
\n\n

¿Por qué jvmTarget es una cadena? Porque Kotlin espera una representación de cadena de la versión (por ejemplo, "1.8", "11", "17"). Si intenta pasar JavaVersion.VERSION_11, el compilador mostrará un error.

\n\n

Ejemplo completo de build.gr

Blogs

Book Recommendations