Compile with Java 11 to Java 8 language level

Hi,

I’m using Gradle 6.7.1.
What is the best way to compile with Java11 compiler, but to a language level of Java8?

I couldn’t understand from the doc of Javatoolchain if there’s a way to set the compiler and the language level differently ?

Is there a reason you don’t simply use a Java 8 Toolchain?

You can use the options.release property of the Java compile tasks to “set the target compatibility”.
https://docs.gradle.org/current/userguide/building_java_projects.html#sec:java_cross_compilation

Maybe, maybe not. Depends on what his goal is.
If the answer to my question would for example be “I need Java 11 APIs on the compile class path”, then the --release flag does not help, as it also restricts the accessible API. :wink:

Or to show some concrete alternatives:

This will result in Java 8 compatible bytecode and will restrict the API to Java 8 too

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(11))
    }
}

tasks.compileJava {
    options.release.set(8)
}

This will set source and target compatibility to Java 8 but will still allow to use Java 11 API

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(11))
    }
}

tasks.compileJava {
    sourceCompatibility = "${JavaVersion.VERSION_1_8}"
}

This will use the Java 8 toolchain for exactly that task:

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(11))
    }
}

tasks.compileJava {
    javaCompiler.set(javaToolchains.compilerFor {
        languageVersion.set(JavaLanguageVersion.of(8))
    })
}

There are many different ways, depending on the actual needs. :slight_smile:

Correct, I implied intent based on what I consider the average. :slight_smile:

I consider the average/most common intent to be, “I have a newer JDK but I need to produce bytecode that will run on an older JRE.”

1 Like

Thanks for you answers. My goal is what Chris has said: "“I have a newer JDK but I need to produce bytecode that will run on an older JRE.”

Ok, it was just because you said “to set the compiler and the language level differently”.
Because then you could also simply set the Java Toolchain accordingly to Java 8.
If you use the --release you cannot run your build with Java 8, as it does not yet support that option.
If you use Java Toolchains, it doesn’t matter with which Java version that the Groovy version you use supports the build is run, becuase the Java with which you run Gradle is only used if it satisfies the Java Toolchain settings and if it does not, for example you run Gradle with Java 11 but configured a Java 8 Toolchain, then one of the discovered or auto-provisioned JVMs that matches your specification is used to compile your code, so in this case there is no difference between the compiler used and the language level as with the toolchain you define the compiler to use. :slight_smile: