blog-2024-02-09

## JVM bytecode level selection with kotlin and gradle

Given the following problem:

* a [Gradle]-[kotlin] multimodule project
* several modules containing [kotlin] code
* targetting the [JVM]
* developed locally with a JDK-21 and on the build server with a JDK-17, targetting both JRE 11 and JRE 17.


toolchain selection does not equal bytecode level selection. i had the problem that locally, i was using a [JDK] 21 while having all other JDKs (1.8, 11, 17, 21 and various graalvm) installed. one user required JRE 11 (bytecode level 55) compatibility, while a server application from the same project had to run on a [JRE] 17.

setting gradle's toolchain selection for the [kotlin] plugin to 11 worked locally but failed on the build server, which used an JDK 17 image.

the solution that finally worked was defining the following properties for every module:

```kotlin
kotlin {
    compilerOptions {
        // 11 for all libraries and 17 for the one server module
        jvmTarget.set(JvmTarget.JVM_11)
    }
}

java {
    // 11 for all libraries and 17 for the one server module
    targetCompatibility = JavaVersion.VERSION_11
}
```

what doesn't work

```
kotlin {
    jvmToolchain(11)
}

``` 
this works locally, where JDK 11 is among the JDKs installed, but fails on the build server where the only JDK present is 17 (so no automatic 17-to-11 compatibility assumption).

several factors are at play here:

1. the bytecode version generated by the kotlin compiler
2. the bytecode version generated by the java compiler
3. the java toolchain used


while i got it to work i feel like i'm stuck in a dangerous half-knowledge state.

edited by: stefs at Friday, February 9, 2024, 11:22:42 AM Coordinated Universal Time


view