skip to content

How do you disable JDK auto-download, and why might a team do that in CI?

level: middleimportance: must knowfreq 48%

answer

  1. org.gradle.java.installations.auto-download=false
  2. gradle.properties or -D/-P
  3. fail fast, no fetch
  4. CI reproducibility + supply chain
  5. installations.paths to point at JDKs

basics

~10 s

Set org.gradle.java.installations.auto-download=false in gradle.properties (or pass it with -P/-D). Gradle then refuses to download missing JDKs and fails if no matching local JDK exists. Teams do this so CI uses only pre-installed, controlled JDKs.

solid answer

~40 s

Auto-download is controlled by the property **`org.gradle.java.installations.auto-download`**. Setting it to `false` (in `gradle.properties`, or via `-Dorg.gradle.java.installations.auto-download=false` / `-Porg...`) tells Gradle to **never** provision a missing toolchain — if no local JDK matches the requested toolchain, the build fails with a clear error instead of fetching one. CI environments often disable it for **reproducibility and supply-chain control**: the JDKs are baked into the build image, so builds never depend on foojay/Disco availability, never pull an unvetted binary, and stay deterministic and offline-friendly. You typically pair this with pre-installed JDKs whose locations Gradle discovers automatically or via `org.gradle.java.installations.paths`. Leaving auto-download enabled is fine for local developer machines where convenience matters more than locked-down sourcing.

code

properties · 3 lines
properties
# gradle.properties (committed for CI)
org.gradle.java.installations.auto-download=false
org.gradle.java.installations.paths=/opt/jdk-17,/opt/jdk-21

go deeper

for a junior

Know the property name and that false stops Gradle from downloading missing JDKs.

for a middle

Explain the CI rationale (reproducibility, offline, supply chain) and how JDKs are then supplied via installations.paths.

for a senior

Discuss layering: keep the plugin for dev, flip the flag per CI job via -D; describe the fail-fast behavior.

for a principal

Set org policy banning build-time binary downloads; standardize pre-provisioned JDKs in images and a controlled fallback resolver.

## The control knob Provisioning is gated by a single Gradle property: ```properties # gradle.properties org.gradle.java.installations.auto-download=false ``` When `false`, Gradle will **detect** locally installed JDKs and use them for toolchains, but it will **never download** a missing one. If a toolchain request can't be satisfied locally, the build fails fast with a message naming the required version and the installations it inspected. You can set it three ways (later wins): in `gradle.properties` (project or `~/.gradle/`), as a system property `-Dorg.gradle.java.installations.auto-download=false`, or via `-P`. The system-property form is handy for overriding per CI job. ## Why disable it in CI 1. **Reproducibility** — the exact JDK ships in the build image; a build can't silently start using a newer patch release pulled from the internet. 2. **Supply-chain / security** — no build-time download of a binary from an external API; nothing to vet at runtime. Many orgs forbid build-time fetches of executables. 3. **Offline / air-gapped builds** — agents with no internet (or a locked-down proxy) would otherwise fail slowly trying to reach the Disco API. 4. **Speed & flakiness** — removes a network dependency that can intermittently fail or rate-limit. ## How CI then supplies the JDK With download off, you make the right JDK **discoverable**: - Install it in the image (most CI base images set up well-known JDK locations Gradle auto-detects). - Or point Gradle at explicit paths: ```properties org.gradle.java.installations.paths=/opt/jdk-17,/opt/jdk-21 ``` Gradle then matches the toolchain request against these installations. ## Interaction with the resolver plugin Disabling download does **not** require removing the foojay plugin — the property short-circuits provisioning regardless of which resolvers are registered. So you can keep the convention plugin for local dev and flip the property off in CI. ## Failure behavior With download off and no match found, you get an error like *"No compatible toolchains found ... Auto-download is not enabled."* — a deliberate, actionable failure rather than a surprise download.

  • If you disable auto-download, how does Gradle still find the right JDK?
    Through local detection of installed JDKs, optionally augmented by `org.gradle.java.installations.paths` listing explicit JDK directories.
  • Do you have to remove the foojay plugin to disable downloads?
    No. The auto-download property short-circuits provisioning regardless of which resolvers are registered, so you can keep the plugin for local dev.
  • What happens if download is off and no matching JDK exists?
    The build fails fast with an error stating no compatible toolchain was found and that auto-download is disabled.

saying these in an interview costs you the question

  • Claiming you must uninstall the foojay plugin to stop downloads (the property suffices).
  • Thinking auto-download=false also disables local JDK detection (it only disables fetching).

context