Как настроить совместимость JVM для compileJava (Java 11) и compileKotlin (Kotlin 1.8) в build.gradle.kts?
Проблема: разные JVM target для Java и Kotlin
Вы столкнулись с типичной ситуацией в смешанных проектах Java+Kotlin. Задача compileJava и compileKotlin по умолчанию используют разные версии JVM, если не задать явные настройки. Решение — синхронизировать их через единый параметр.
Решение: используйте kotlin.jvmTarget и java.targetCompatibility
Самый правильный способ — задать JVM target для Kotlin через блок kotlin { jvmToolchain { ... } } или напрямую через tasks.withType. Одновременно настройте Java через java { targetCompatibility = ... }. Вот полный пример:
plugins {
java
kotlin("jvm") version "1.8.0"
}
// Глобальная настройка Java
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
// Настройка Kotlin JVM target
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile> {
kotlinOptions.jvmTarget = "11"
}
// Альтернативный вариант через kotlin блок (если используете kotlin-dsl)
kotlin {
jvmToolchain(11) // Устанавливает и Java, и Kotlin на одну версию
}
Почему это работает?
java.targetCompatibility— задаёт версию байт-кода для Java-компилятора.kotlinOptions.jvmTarget— задаёт версию байт-кода для Kotlin-компилятора.- Если используете
jvmToolchain(11), Gradle автоматически подтянет JDK 11 и применит его ко всем задачам.
Важные нюансы
- Убедитесь, что у вас установлен JDK 11 или выше (проверьте
java -version). - Если проект мультимодульный, настройки нужно продублировать в каждом подпроекте или вынести в
allprojects { ... }. - Для Gradle 7+ рекомендуется использовать
jvmToolchain— это упрощает управление версиями. - Если вы используете
options.release.set(11)для JavaCompile, это эквивалентноtargetCompatibility, но более новый способ. Однако для Kotlin это не работает — нужно явно задаватьjvmTarget.
Полный проверенный пример build.gradle.kts
plugins {
java
kotlin("jvm") version "1.8.0"
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlin {
jvmToolchain(11)
}
tasks.withType<JavaCompile> {
options.release.set(11)
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile> {
kotlinOptions.jvmTarget = "11"
}
После этого обе задачи будут компилировать в байт-код для JVM 11. Проверить можно, запустив gradle build — ошибки совместимости исчезнут.
Альтернативный подход: использовать kotlin-dsl и единый блок kotlin { }
Если вы используете Kotlin DSL и хотите минимизировать код, можно применить более лаконичный вариант через kotlin { jvmToolchain { ... } }. Этот блок автоматически настраивает и Java, и Kotlin на одну версию JVM, если у вас установлен соответствующий JDK.
plugins {
java
kotlin("jvm") version "1.8.0"
}
kotlin {
jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(11))
}
}
Этот способ особенно удобен в мультимодульных проектах, так как Gradel сам подтянет нужный JDK для компиляции. Однако он требует, чтобы JDK 11 был доступен через toolchain (например, установлен локально или через Adoptium).
Когда использовать: если вы не хотите дублировать настройки для Java и Kotlin отдельно, и ваш проект использует Gradle 7+ с поддержкой toolchain. Минус — может не сработать, если у вас старый Gradle.