Compiling a Gradle Java project with Java 8 but running tests with Java 11

As the first part of a transition process of my projects, I would like to keep compile with JDK-8 compiler, but execute tests with JDK-11 runtime.

My projects are Gradle projects (6.+ if it matters), using the java plugin or java-library plugins.

I could not find a way to do it with Gradle options.

I tried to compile ( gradlew build ) in one terminal with JDK-8, and then switch to another terminal with JDK 11 and run the tests ( gradlew test ), but it re-compiled the code.

What is the correct way to do it?

If you just want to run your tests with a different version of Java, you just need to specify a different Java executable to use for Test tasks.

tasks.withType(Test) {
    executable = new File("${PATH_TO_TEST_JAVA_RUNTIME}", 'bin/java')
}

Note that ${PATH_TO_TEST_JAVA_RUNTIME} is nothing special. It is just a placeholder that you can replace that with any sort of property lookup/variable/path that you want.

Thanks for your comment, but I don’t see any property named executable in Task API

That’s correct. An executable is not universal to all tasks and therefore is not part of the generic Task interface. It is specifically part of an interface implemented by some Tasks, such as Test, where it is relevant.

You might also be interested in the toolchain support added in Gradle 6.7. Specifically the section on specifying custom toolchains for individual tasks.

Following this question, Is setting executable enough for running tests with JDK-11?
I was thinking later that perhaps bootstrapClasspath should be set as well. Am I missing something?

You don’t need a bootstrap classpath for the case where you want to compile with Java 8, but then run it on a newer version of Java. It’s primarily for the opposite case you might want to compile with Java 11, but guarantee compatibility with Java 8.