How do you constrain a Gradle JVM toolchain to a specific JDK vendor, and what does adding a vendor do beyond just setting the language version?
answer
- vendor = JvmVendorSpec.ADOPTIUM
- narrows detection + provisioning
- languageVersion required, vendor optional
- reproducible across machines/CI
- default = any vendor
basics
~10 sInside the toolchain block you set languageVersion and add vendor = JvmVendorSpec.ADOPTIUM. The vendor narrows detection/provisioning so only that distribution's JDK matches, not just any JDK of the right version.
solid answer
~40 sA toolchain in Gradle is a declarative description of the JDK used to compile/test/run, decoupled from the JDK that runs Gradle itself. Minimally you only set the language version: ```kotlin java { toolchain { languageVersion = JavaLanguageVersion.of(21) vendor = JvmVendorSpec.ADOPTIUM } } ``` Without a `vendor`, Gradle matches ANY installed/provisionable JDK of version 21. Adding `vendor` adds a second constraint: the toolchain spec now only matches Eclipse Temurin (Adoptium). During **local detection** Gradle filters discovered JDKs by vendor; during **auto-provisioning** it asks the resolver (e.g. Foojay) for that specific distribution. This makes builds reproducible — every machine compiles with the same vendor, avoiding subtle behavioural differences (e.g. JIT, GC defaults, bundled certs) between distributions.
code
kotlin · 6 linesjava {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
vendor = JvmVendorSpec.ADOPTIUM
}
}go deeper
Know the toolchain {} block, that vendor = JvmVendorSpec.ADOPTIUM narrows which JDK is selected, and that languageVersion is the required part.
Explain that vendor filters both local detection and provisioning, and why pinning improves reproducibility.
Discuss the distinction between the Gradle JVM and the toolchain JVM, and the resolution order (detect, then provision).
Frame vendor pinning as an org-wide reproducibility/supply-chain policy decision baked into a convention plugin.
## What a toolchain is A **JVM toolchain** is Gradle's abstraction for "which JDK should compile, test and run my code", expressed as *requirements* rather than a hard-coded path. It is configured in the `java { toolchain { ... } }` block (provided by the `JavaPluginExtension`). Gradle then **resolves** that spec to a concrete JDK by (a) searching JDKs already on the machine (*local detection*) and, if none match and provisioning is enabled, (b) downloading one (*auto-provisioning*, typically via the Foojay Disco resolver plugin). The spec is a `JavaToolchainSpec` with three constraints: - `languageVersion` — a `JavaLanguageVersion` (e.g. `JavaLanguageVersion.of(21)`). The only **required** one. - `vendor` — a `JvmVendorSpec` (e.g. `ADOPTIUM`, `AZUL`, `AMAZON`, `BELLSOFT`, `GRAAL_VM`, `IBM`, `ORACLE`). Optional; default is "any vendor". - `implementation` — a `JvmImplementation` (`VENDOR_SPECIFIC` default, or `J9` for OpenJ9-based builds). Optional. ## Why declare a vendor Without a vendor, two developers can compile the same project with Temurin 21 and Azul Zulu 21 — usually fine, but distributions differ in bundled CA certs, default GC/JIT tuning, packaged tools, and occasionally backported fixes. Pinning a vendor makes the build **reproducible across machines and CI**. ```kotlin java { toolchain { languageVersion = JavaLanguageVersion.of(21) vendor = JvmVendorSpec.ADOPTIUM } } ``` Groovy DSL: ```groovy java { toolchain { languageVersion = JavaLanguageVersion.of(21) vendor = JvmVendorSpec.ADOPTIUM } } ``` ## How the constraint is applied - **Local detection:** Gradle enumerates JDKs (env vars, OS locations, `org.gradle.java.installations.paths/fromEnv`), reads each JDK's vendor from its `release` metadata, and keeps only those whose vendor matches `JvmVendorSpec.ADOPTIUM`. - **Auto-provisioning:** the requested vendor is passed to the resolver; Foojay maps `ADOPTIUM` → the Temurin distribution and downloads it. If nothing matches and provisioning can't satisfy it, the build fails fast with a clear toolchain-resolution error rather than silently using the wrong JDK. ## Vendor specs `JvmVendorSpec` exposes named constants for common vendors and `JvmVendorSpec.matching("...")` for an arbitrary substring match against the JDK's vendor string. The named constants are preferred because they encode the known aliases each vendor uses in its `release` file.
- What happens at resolution time if no installed JDK matches the requested vendor?Gradle tries auto-provisioning (if enabled and a resolver is configured) to download a matching distribution; if that also fails, the build errors with a toolchain-resolution failure rather than falling back to a wrong JDK.
- Is vendor required?No. Only `languageVersion` is required. Omitting `vendor` means any vendor's JDK of the right version is acceptable.
saying these in an interview costs you the question
- Saying vendor changes the bytecode/language version — it only adds a matching constraint, version is independent.
- Claiming Gradle runs on the toolchain JDK — Gradle runs on its own JVM; the toolchain is for compile/test/run of your code.