What is JDK auto-provisioning in Gradle, and what makes it work?
answer
- Gradle ships no JDK URLs
- resolver plugin in settings
- foojay-resolver-convention
- Disco API catalog
- cached in ~/.gradle/jdks
basics
~10 sIf a build needs a JDK that isn't installed locally, Gradle can automatically download it. By default Gradle needs a toolchain resolver plugin (foojay-resolver) registered in settings to know where to fetch JDKs from.
solid answer
~30 sAuto-provisioning lets Gradle download a matching JDK when the toolchain you declared (e.g. `languageVersion = JavaLanguageVersion.of(21)`) isn't found among locally installed JDKs. Gradle itself ships no download URLs; it delegates to **toolchain resolver plugins**. The standard one is `org.gradle.toolchains.foojay-resolver-convention`, applied in `settings.gradle.kts`. It queries the foojay Disco API to find a JDK matching your language version, vendor, and implementation, downloads it, and caches it under the Gradle user home (`~/.gradle/jdks`). Once downloaded it's reused across builds. Auto-provisioning only triggers when no suitable local JDK exists, so adding the plugin is safe even on machines that already have the right JDK.
code
kotlin · 11 lines// settings.gradle.kts
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0"
}
// build.gradle.kts
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}go deeper
Know that a missing JDK can be auto-downloaded and that the foojay-resolver plugin enables it in settings.
Explain the resolver SPI, that Gradle ships no URLs, and that foojay queries the Disco API and caches under ~/.gradle/jdks.
Discuss the convention plugin wiring toolchainManagement automatically, trigger conditions, and reuse/caching semantics.
Frame provisioning as a vendor-neutral SPI choice; weigh build-time downloads vs. pre-provisioned images for org-wide reproducibility.
## The problem auto-provisioning solves A Gradle build can declare which JDK it wants to compile and run with via a **toolchain**: ```kotlin java { toolchain { languageVersion = JavaLanguageVersion.of(21) } } ``` Gradle first scans for **locally installed JDKs** (from well-known locations, `JAVA_HOME`, SDKMAN, asdf, etc.). If it finds a JDK 21, it uses it. If it doesn't, rather than failing the build, Gradle can **auto-provision** — download a matching JDK on the fly. ## Why Gradle needs a resolver plugin Gradle core deliberately does **not** know where to download JDKs from — it ships no vendor URLs. Instead it exposes a **toolchain provisioning SPI** and delegates to **toolchain resolver plugins** registered in `settings.gradle.kts` under `toolchainManagement`. The conventional resolver is the **Foojay Disco resolver**: ```kotlin // settings.gradle.kts plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.9.0" } ``` The `-convention` variant is convenient: it both registers the resolver **and** wires it into `toolchainManagement.jvm.javaRepositories` for you with sensible defaults, so you don't have to write the repository block by hand. ## What foojay does [foojay.io](https://foojay.io) hosts the **Disco API**, a vendor-neutral catalog of JDK builds (Temurin, Zulu, Liberica, Oracle, etc.). When provisioning is needed, the resolver asks the Disco API for a build matching the requested **language version**, **vendor**, and **implementation** (e.g. J9 vs HotSpot), gets back a download URL, and Gradle fetches and unpacks it. ## Caching and reuse Provisioned JDKs land in `~/.gradle/jdks/` (the Gradle user home). They are reused across all builds on that machine — provisioning happens once per (version, vendor) combination, not per build. Gradle verifies the download's integrity. ## When it triggers Auto-provisioning fires **only** when: 1. A toolchain is requested, and 2. No matching JDK is found locally, and 3. `org.gradle.java.installations.auto-download` is not `false`. So applying the plugin is harmless on machines that already have the JDK — it simply never downloads.
- Why doesn't Gradle download JDKs out of the box without any plugin?Gradle core stays vendor-neutral and ships no download URLs; it delegates to pluggable toolchain resolvers so the choice of JDK source isn't baked into Gradle.
- Where are auto-provisioned JDKs stored?Under the Gradle user home, in `~/.gradle/jdks/`, and reused across builds on that machine.
Gradle is like a build coordinator who knows it needs a 'JDK 21 specialist' but has no phone book; the foojay resolver is the phone book it calls to find and hire one.
saying these in an interview costs you the question
- Claiming Gradle downloads JDKs natively with no plugin needed (it needs a toolchain resolver).
- Saying provisioning happens on every build (it's cached and reused).