Why and how would you disable auto-detection with org.gradle.java.installations.auto-detect=false?
answer
- false = stop scanning managers/OS dirs
- only paths/fromEnv + launching JVM remain
- determinism + speed + hermeticity
- auto-detect != auto-download
- hardened combo: detect off + download off + fromEnv
basics
~10 sSet org.gradle.java.installations.auto-detect=false to stop Gradle scanning managers and OS dirs. You then supply JDKs only via installations.paths/fromEnv. It's used on locked-down CI to make the JDK set deterministic and the build fast.
solid answer
~50 s`org.gradle.java.installations.auto-detect=false` turns off the automatic scanning of SDKMAN, asdf, Homebrew, OS directories, etc. After disabling it, Gradle only considers JDKs you provide explicitly through `org.gradle.java.installations.paths` and `org.gradle.java.installations.fromEnv` (plus the JVM running Gradle). Reasons to disable: - **Determinism**: on a shared or CI machine, scanning might find an unexpected JDK and silently satisfy a toolchain with the wrong build, hurting reproducibility. Explicit lists make the candidate set exact. - **Performance**: probing many discovered installations adds startup cost; pruning to a known few speeds configuration, especially in containers with several JDKs. - **Hermetic/sandboxed builds**: locked-down environments forbid wandering the filesystem; you want only declared, audited JDKs. Note `auto-detect` controls *discovery of installed JDKs*; it does **not** by itself control *downloading* — auto-provisioning is governed separately by `org.gradle.java.installations.auto-download`. A common hardened combo is `auto-detect=false` + `auto-download=false` + explicit `fromEnv`, so the build uses exactly the JDKs the CI image injected and nothing else.
code
bash · 5 lines# Hermetic CI invocation: only the injected JDKs, no scanning, no downloads
./gradlew build \
-Dorg.gradle.java.installations.auto-detect=false \
-Dorg.gradle.java.installations.auto-download=false \
-Dorg.gradle.java.installations.fromEnv=JDK17,JDK21go deeper
Know the flag exists and that false stops the automatic scanning.
Explain what's lost (manager/OS scanning) and what still works (paths/fromEnv/launching JVM).
Justify it for CI determinism/speed/hermeticity and pair it correctly with auto-download.
Define org-wide policy: detection on for dev ergonomics, off + explicit allowlist on CI, governed via agent-level properties.
## What the flag controls `org.gradle.java.installations.auto-detect` (default `true`) governs whether Gradle runs its **installation suppliers** — the routines that scan SDKMAN, asdf, Jabba, Homebrew, and standard OS JDK directories. Set it to `false` and those suppliers are skipped. Gradle then knows about only: - the JVM that launched Gradle (always considered), and - JDKs you list via `org.gradle.java.installations.paths` and `...fromEnv`. ## Why disable it ### Reproducibility / determinism On a developer laptop or a fat CI image there may be five JDKs lying around. Auto-detection could match a toolchain to whichever one happens to be present, so two machines "satisfy" the same spec with *different* builds (different patch versions or vendors). Disabling detection and enumerating an exact list removes that nondeterminism — the candidate set is whatever you declared, full stop. ### Performance Every discovered installation is probed (a subprocess to read version/vendor). Dozens of installations = measurable configuration-time overhead. Trimming to the few you actually need speeds up the build, which matters in short-lived CI containers. ### Hermeticity / security Sandboxed or audited build environments may disallow scanning arbitrary filesystem locations. An explicit allowlist of audited JDKs is easier to reason about and review. ## How to configure ```properties # gradle.properties org.gradle.java.installations.auto-detect=false org.gradle.java.installations.auto-download=false # also forbid provisioning org.gradle.java.installations.fromEnv=JDK17,JDK21 # the only JDKs allowed ``` ## Don't confuse the two flags | Property | Controls | Default | |---|---|---| | `auto-detect` | scanning the machine for *installed* JDKs | `true` | | `auto-download` | *downloading* a JDK when none matches (provisioning) | `true` | Disabling detection alone does **not** stop downloads; if a spec can't be met from your explicit list, Gradle may still try to provision. The fully-locked configuration disables both and relies on `fromEnv`. ## Failure mode With detection off and no explicit JDK matching a declared toolchain (and downloads off), the build fails with a clear "No compatible toolchains found" error — which is the *intended* hermetic behavior: fail loudly rather than silently use the wrong JDK. Diagnose with `./gradlew javaToolchains`, which under `auto-detect=false` lists only the explicit set. ## When NOT to disable On developer machines, detection is a big convenience — it lets contributors build with whatever JDK their version manager installed. Reserve `auto-detect=false` for CI and locked environments, typically via `~/.gradle/gradle.properties` on the agent or a `-D` flag, not the committed project file (so local devs keep the convenience).
- Does auto-detect=false also stop Gradle from downloading a JDK?No. Downloading is auto-provisioning, controlled by org.gradle.java.installations.auto-download. To fully lock things down you disable both flags.
- Where should you put auto-detect=false so local developers aren't inconvenienced?In the CI agent's ~/.gradle/gradle.properties or as a -D flag in the pipeline, not in the committed project gradle.properties — local devs keep the convenience of scanning their version manager.
- What error appears if no JDK matches under a fully locked config?'No compatible toolchains found' (or similar), which is the intended fail-loud behavior; ./gradlew javaToolchains then shows only the explicit installations.
saying these in an interview costs you the question
- Claiming auto-detect=false prevents JDK downloads (that's auto-download).
- Putting auto-detect=false in committed project config, breaking every contributor's local build convenience.
- Disabling detection but forgetting to supply paths/fromEnv, so no JDK is available at all.