Multi-Release JARs can be used for this.
Multi-Release JARs allow to create classes that are loaded only in specific Java versions.
You can do that by specifying a source set for Java 17 and keeping your main source set for Java 11.
You make the Java 17 source set to use be able to access Java 11 code as well.
Furthermore, you specify a task for compiling Java 17 code with a custom source and target compatibility and the source set for Java 17.
Normal (Java 11) source code goes to src/main/java
will Java 17 source code goes to src/java17/java
.
When creating a JAR, the Java 17 build output is moved to META-INF/versions/16
making it available for Java 16+ only.
Using the Kotlin DSL, your build.gradle.kts
could look like this:
plugins {
id("java")
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
//Java 11 dependencies here (available for all code)
}
tasks {
jar {//configure JAR creation
dependsOn("compileJava17")//requires Java 17 code to be built
into("META-INF/versions/17") {//move Java 17 code into META-INF/versions/17
from(sourceSets["java17"].output)//take it from Java 17 output folder
}
manifest {
attributes("Multi-Release" to "true")//configure it to be recognized as a Multi-Release JAR
}
}
}
sourceSets.create("java17") {//create Java 17 source set
this.java.srcDir("src/java17/java")//where to put sources
dependencies {
//Java 17 dependencies here (only available for Java 17 code)
}
//include Java 11 source code (make it accessible from Java 17)
compileClasspath += sourceSets["main"].output
runtimeClasspath += sourceSets["main"].output
}
java {
//configure project to use Java 11
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceSets["main"]//use main source set
}
task<JavaCompile>("compileJava17") {//create task for Java 17
dependsOn("compileJava")//requires normal Java compilation to be finished
//set source and target compatibility
sourceCompatibility = JavaVersion.VERSION_17.name
targetCompatibility = JavaVersion.VERSION_17.name
sourceSets["java17"]//use Java 17 source set
}