Gradle
JDK version
Java Development Kit
programming
software development

How do I tell Gradle to use specific JDK version?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

The modern way to tell Gradle to use a specific JDK version is with Java Toolchains, available since Gradle 6.7. Toolchains let you declare the required Java version in your build script, and Gradle automatically locates (or downloads) the right JDK. This article covers toolchains and every other method, so you can pick the right approach for your situation.

Java Toolchains decouple the JDK used to run Gradle from the JDK used to compile your code. You declare the language version in your build script, and Gradle does the rest.

build.gradle (Groovy DSL):

groovy
1java {
2    toolchain {
3        languageVersion = JavaLanguageVersion.of(21)
4    }
5}

build.gradle.kts (Kotlin DSL):

kotlin
1java {
2    toolchain {
3        languageVersion.set(JavaLanguageVersion.of(21))
4    }
5}

When you run ./gradlew build, Gradle will:

  1. Search for a JDK 21 installation on your machine (checking standard locations and environment variables)
  2. If not found, automatically download one (from Adoptium by default, since Gradle 7.6)
  3. Use that JDK for compilation, test execution, and Javadoc generation

Specifying Vendor and Implementation

You can be more specific about which JDK distribution to use:

groovy
1java {
2    toolchain {
3        languageVersion = JavaLanguageVersion.of(21)
4        vendor = JvmVendorSpec.AMAZON     // Corretto
5        // Other options: ADOPTIUM, ORACLE, GRAAL_VM, IBM, SAP, MICROSOFT
6    }
7}

Verifying Which Toolchain Gradle Selected

bash
./gradlew -q javaToolchains

Example output:

 
1 + Java 21.0.2
2     | Location:    /usr/lib/jvm/java-21-openjdk
3     | Language:    21
4     | Vendor:      Eclipse Adoptium
5     | Is default:  true

Method 2: JAVA_HOME Environment Variable

Setting JAVA_HOME tells Gradle which JDK to use for running Gradle itself and (by default) compiling code.

Linux / macOS:

bash
1# For current session
2export JAVA_HOME=/usr/lib/jvm/java-21-openjdk
3
4# Permanent (add to ~/.bashrc, ~/.zshrc, etc.)
5echo 'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk' >> ~/.bashrc
6source ~/.bashrc

Windows (Command Prompt):

batch
set JAVA_HOME=C:\Program Files\Java\jdk-21

Windows (PowerShell, permanent):

powershell
[Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\Program Files\Java\jdk-21", "User")

Verify it took effect:

bash
./gradlew --version

The output shows "JVM" with the Java version Gradle is using.

When to use JAVA_HOME vs. Toolchains

JAVA_HOME controls the JDK that runs the Gradle daemon. Toolchains control the JDK that compiles your code. These can be different. For example, you can run Gradle on Java 21 while compiling your project with Java 17 via toolchains.

Method 3: gradle.properties

The org.gradle.java.home property overrides JAVA_HOME for Gradle specifically:

gradle.properties (project root):

properties
org.gradle.java.home=/usr/lib/jvm/java-21-openjdk

Per-user default (in ~/.gradle/gradle.properties):

properties
org.gradle.java.home=/usr/lib/jvm/java-21-openjdk

The project-level file takes precedence over the user-level file.

From the command line (one-off):

bash
./gradlew build -Dorg.gradle.java.home=/usr/lib/jvm/java-21-openjdk

Important caveat

Do not commit a gradle.properties with a hardcoded absolute path. Paths vary across machines and operating systems. Use toolchains instead for portable builds, and reserve org.gradle.java.home for local overrides.

Method 4: sourceCompatibility and targetCompatibility (Cross-Compilation)

These settings tell the Java compiler to produce bytecode compatible with a specific Java version, without requiring a different JDK installation:

groovy
1java {
2    sourceCompatibility = JavaVersion.VERSION_11
3    targetCompatibility = JavaVersion.VERSION_11
4}

Or equivalently in tasks:

groovy
tasks.withType(JavaCompile).configureEach {
    options.release = 11   // Preferred since Gradle 6.6 / javac --release
}

The --release flag is better than sourceCompatibility/targetCompatibility because it also enforces API compatibility. With just sourceCompatibility = 11, you could accidentally use Java 21 APIs that do not exist in Java 11. The --release 11 flag prevents that.

Method 5: Per-Task JDK Configuration

For fine-grained control, you can set the JDK on individual tasks:

groovy
1tasks.withType(JavaCompile).configureEach {
2    javaCompiler = javaToolchains.compilerFor {
3        languageVersion = JavaLanguageVersion.of(17)
4    }
5}
6
7tasks.withType(Test).configureEach {
8    javaLauncher = javaToolchains.launcherFor {
9        languageVersion = JavaLanguageVersion.of(21)
10    }
11}
12
13tasks.withType(Javadoc).configureEach {
14    javadocTool = javaToolchains.javadocToolFor {
15        languageVersion = JavaLanguageVersion.of(17)
16    }
17}

This is useful when you need to compile with JDK 17 but run tests against JDK 21 to verify forward compatibility.

Gradle and JDK Compatibility Reference

Not all Gradle versions support all JDK versions. Here is the compatibility:

Gradle VersionMinimum JDKMaximum JDKToolchain Support
8.10+823Yes
8.5-8.9822Yes
8.0-8.4820Yes
7.6819Yes (auto-download)
7.0-7.5818Yes (manual install)
6.7-6.9816Yes (basic)
6.0-6.6815No

If you are on an older Gradle, upgrade the Gradle Wrapper first:

bash
./gradlew wrapper --gradle-version 8.10

Complete Working Example

Here is a full build.gradle.kts for a project that requires JDK 21:

kotlin
1plugins {
2    java
3    application
4}
5
6java {
7    toolchain {
8        languageVersion.set(JavaLanguageVersion.of(21))
9    }
10}
11
12application {
13    mainClass.set("com.example.Main")
14}
15
16repositories {
17    mavenCentral()
18}
19
20dependencies {
21    testImplementation("org.junit.jupiter:junit-jupiter:5.11.0")
22}
23
24tasks.test {
25    useJUnitPlatform()
26}

Running ./gradlew run on this project will automatically use JDK 21, downloading it if necessary.

Common Pitfalls

  • Confusing the Gradle JVM with the compilation JDK. Gradle itself runs on one JDK (set by JAVA_HOME or org.gradle.java.home), but your project can compile with a completely different JDK via toolchains. These are separate concerns.
  • Committing absolute paths in gradle.properties. This breaks builds on other machines. Use toolchains for reproducible builds across different environments.
  • Setting sourceCompatibility without --release. sourceCompatibility = 11 with a JDK 21 compiler lets you use Java 21 APIs that do not exist in Java 11. The code compiles but fails at runtime. Use options.release = 11 instead.
  • Forgetting to update the Gradle Wrapper. Old Gradle versions do not support new JDKs. Always check the Gradle-JDK compatibility table and update the wrapper if needed.
  • IDE using a different JDK than Gradle. IntelliJ, Eclipse, and VS Code each have their own JDK settings. If your IDE compiles fine but ./gradlew build fails, check that the IDE imports the Gradle project's toolchain configuration.
  • CI/CD not having the required JDK installed. If your CI server does not have JDK 21 and toolchain auto-download is disabled (which is the default in some environments), the build fails. Either pre-install the JDK or enable auto-provisioning with the Gradle Toolchain Resolver plugin.

Summary

  • Use Java Toolchains (Gradle 6.7+) for portable, reproducible JDK configuration. Declare languageVersion in your build script.
  • Use JAVA_HOME to control which JDK runs the Gradle daemon.
  • Use org.gradle.java.home in gradle.properties for local overrides, but never commit absolute paths.
  • Use options.release instead of sourceCompatibility/targetCompatibility for cross-compilation to prevent accidental use of newer APIs.
  • Verify your setup with ./gradlew -q javaToolchains and ./gradlew --version.
  • Check the Gradle-JDK compatibility table before upgrading either Gradle or your JDK.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.