Gradle JVM Compatibility: How to Make Kotlin 1.8 and Java 11 Work Together

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Why does your Kotlin and Java project suddenly "fall apart"?

\n\n

Have you ever encountered a situation where you write code in Kotlin, use Java 11 for the main code, and Gradle suddenly throws a compatibility error? Sounds familiar? This is one of the most common problems when configuring multi-module projects. Especially when you use build.gradle.kts (Kotlin DSL) and try to make compileJava work with compileKotlin. In this article, we'll break down how to correctly set jvm target compatibility for Java 11 and Kotlin 1.8 so that your project builds without errors. And yes, we'll do it with humor and without boring theory.

\n\n

If you came from Stack Overflow, you know that the original question has gathered thousands of views. We are adapting it into an educational format so that you don't just copy the answer, but understand why the error occurs and how to avoid it in the future.

\n\n

The Problem: When Java and Kotlin Speak Different Languages

\n\n

Imagine Java 11 is a strict professor who demands everything to be by the standard. And Kotlin 1.8 is its creative colleague who wants to use new features but forgets to inform the professor. The result is a conflict.

\n\n

In Gradle, each compilation task (compileJava, compileKotlin) has its own JVM target — the bytecode version into which the code is compiled. If they don't match, you'll get an error like:

\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

Or, even worse, a silent performance drop due to bytecode incompatibility.

\n\n

Why does this happen specifically in build.gradle.kts?

\n\n

Kotlin DSL (.gradle.kts files) is a powerful tool, but it requires explicit parameter specification. Unlike Groovy DSL, where some settings are "picked up" automatically, in Kotlin DSL you need to be precise. This is especially true for the jvm target.

\n\n

A typical mistake: you set java.targetCompatibility = JavaVersion.VERSION_11, but forget to specify the same for Kotlin. Or vice versa — you configure compileKotlin, but compileJava remains on Java 8.

\n\n

The Correct Solution: A Unified JVM Target for Java and Kotlin

\n\n

To avoid errors, you need to explicitly set the jvm target for both tasks. Here's how to do it in build.gradle.kts:

\n\n

Step 1. Configuring Java (compileJava)

\n\n

Add the following to the java {} block or to 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

Note: sourceCompatibility and targetCompatibility must be the same. If you write code in Java 11, the bytecode should also be Java 11.

\n\n

Step 2. Configuring Kotlin (compileKotlin)

\n\n

Now the most important part — set the jvm target for Kotlin. This is done through the kotlin {} block or via tasks.withType<KotlinCompile>():

\n\n
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\ntasks.withType<KotlinCompile>() {\n    kotlinOptions {\n        jvmTarget = "11"  // Note: this is a string, not a JavaVersion!\n        apiVersion = "1.8"\n        languageVersion = "1.8"\n    }\n}\n
\n\n

Why is jvmTarget a string? Because Kotlin expects a string representation of the version (e.g., "1.8", "11", "17"). If you try to pass JavaVersion.VERSION_11, the compiler will throw an error.

\n\n

Full example of build.gr

Blogs

Book Recommendations