Как настроить совместимость JVM для задач compileJava (11) и compileKotlin (1.8) в build.gradle.kts?
Правильное решение: используйте свойство kotlin.jvm.target и настройки Java
Ваша проблема распространена среди разработчиков, переходящих с Groovy DSL на Kotlin DSL. Основная причина путаницы — устаревшие примеры из документации. Начиная с Kotlin 1.5.0, для JVM-проектов рекомендуется использовать единый источник истины: свойство kotlin.jvm.target в gradle.properties или прямое указание через kotlin.jvm.target.validation.mode.
Вот самый надёжный способ настроить совместимость JVM для Java 11 и Kotlin 1.8.x в build.gradle.kts:
// build.gradle.kts
plugins {
kotlin("jvm") version "1.8.20"
java
}
// 1. Явно задаём target для Java
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
// 2. Настраиваем Kotlin compiler на ту же версию
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "11" // Важно: строка "11", а не JavaVersion
}
}
// 3. (Опционально) Включаем строгую проверку совпадения версий
kotlin {
jvmToolchain(11) // Устанавливает тулчейн Java 11 для Kotlin-задач
}
Почему это работает?
jvmTarget = "11"— это строка, а не объектJavaVersion. Kotlin принимает именно строковое представление (например, "1.8", "11", "17").jvmToolchain(11)— автоматически синхронизирует Kotlin-компилятор с JDK 11. Это самый чистый способ в Kotlin 1.8+.- Если вы используете
kotlin.jvm.target.validation.mode=errorвgradle.properties, Gradle будет выдавать ошибку при несовпадении версий Java и Kotlin.
Дополнительно про gradle.properties:
Добавьте в файл gradle.properties (в корне проекта) следующее:
kotlin.jvm.target.validation.mode=error
kotlin.code.style=official
Это заставит Gradle строго проверять, что jvmTarget Kotlin совпадает с targetCompatibility Java. Если они различаются — сборка упадёт с ошибкой.
Полный пример для мультимодульного проекта:
// В корневом build.gradle.kts
subprojects {
apply(plugin = "java")
apply(plugin = "kotlin")
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "11"
}
}
}
Важное примечание про версию Kotlin: Начиная с Kotlin 1.8.0, поддержка JVM-таргетов изменилась. Если вы видите предупреждение "Using JVM 11 target is not supported", проверьте:
- Установлен ли у вас JDK 11 (команда
java -version). - Не используете ли вы устаревший плагин Kotlin (версии ниже 1.5.0).
- Не конфликтуют ли
jvmTargetс настройкамиcompileJava.
В 99% случаев решение с jvmToolchain(11) и явным указанием jvmTarget = "11" решает проблему. Если же проект требует Java 8 для совместимости с библиотеками, используйте jvmTarget = "1.8" и sourceCompatibility = JavaVersion.VERSION_1_8.
Альтернативный подход: через kotlin.jvm.target в gradle.properties
Если вы не хотите дублировать версию в каждом модуле, можно использовать единую настройку через gradle.properties. Этот метод особенно удобен для CI/CD, где версия JVM централизованно задаётся переменной окружения.
// gradle.properties (корень проекта)
kotlin.jvm.target=11
Затем в build.gradle.kts достаточно указать только Java-совместимость:
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
Kotlin-задачи автоматически подхватят значение из gradle.properties. Однако этот способ не сработает, если вы явно переопределяете jvmTarget в kotlinOptions — в таком случае приоритет будет у явного указания.
Минусы подхода:
- Меньше контроля — если вам нужно разное значение для разных модулей, придётся использовать первый вариант.
- Не все версии Kotlin поддерживают
kotlin.jvm.target(работает с 1.5+).
Рекомендую комбинировать: задать kotlin.jvm.target в gradle.properties как умолчание, а в отдельных модулях переопределять через kotlinOptions, если необходимо.