How do you tell Gradle about JDKs installed in non-standard locations using org.gradle.java.installations.paths and fromEnv?
answer
- paths = comma-separated JDK home dirs
- fromEnv = comma-separated env-var NAMES
- augments, doesn't replace, detection
- fromEnv idiomatic for CI
- verify with ./gradlew javaToolchains
basics
~10 sSet org.gradle.java.installations.paths to a comma-separated list of JDK home directories, or org.gradle.java.installations.fromEnv to a comma-separated list of env-var names whose values are JDK homes. Gradle probes those and adds them to detection.
solid answer
~40 sAuto-detection covers common managers and OS dirs, but JDKs in custom locations (a tarball under `/opt`, a CI-provided home) won't be found automatically. Two properties extend the search: - `org.gradle.java.installations.paths` — a **comma-separated list of absolute JDK home paths**. Gradle probes each directly. - `org.gradle.java.installations.fromEnv` — a **comma-separated list of environment-variable names** (e.g. `JDK17,GRAALVM_HOME`). Gradle reads each var's value as a JDK home and probes it. This is the idiomatic way to surface CI-injected JDKs. Set them in `gradle.properties` (project or `~/.gradle`) or pass as `-D` system properties. These *augment* auto-detection rather than replace it — both the scanned and the explicitly-listed JDKs end up in the registry. Each path is still probed for vendor/version, so a wrong or non-JDK path is ignored with a warning rather than breaking the build.
code
toml · 5 lines# gradle.properties (committed) — names stay stable across machines
org.gradle.java.installations.fromEnv=JDK11,JDK17,JDK21
# ~/.gradle/gradle.properties (per-dev) — absolute homes
org.gradle.java.installations.paths=/opt/jdk-17.0.9,/opt/graalvm-21go deeper
Know the two properties exist and that one takes paths and one takes env-var names.
Choose correctly between paths (machine-local) and fromEnv (CI/shared), and verify with javaToolchains.
Design committed vs per-machine property placement and combine with auto-detect=false for determinism.
Standardize a fromEnv contract across the org's CI images so every pipeline exposes the same JDK variable names.
## Why you need explicit paths Auto-detection knows about *managers* (SDKMAN, asdf, Jabba) and *standard OS directories*. A JDK extracted to an arbitrary path — `/opt/corretto-17`, a vendored tarball in CI, a custom NFS mount — is invisible to those suppliers. The two `installations.*` properties let you register those locations explicitly. ## `org.gradle.java.installations.paths` A comma-separated list of **JDK home directories** (the dir that contains `bin/java`, `lib/`, `release`). Gradle probes each and, if it's a valid JDK, adds it to the toolchain registry: ```properties org.gradle.java.installations.paths=/opt/jdk-17.0.9,/opt/jdk-21.0.2,/nfs/shared/graalvm-21 ``` ## `org.gradle.java.installations.fromEnv` A comma-separated list of **environment-variable names**. Gradle resolves each name to its value and treats that value as a JDK home: ```properties org.gradle.java.installations.fromEnv=JDK11,JDK17,JDK21,GRAALVM_HOME ``` This is the preferred pattern on CI runners (GitHub Actions `setup-java` exports `JAVA_HOME_17_X64` etc.; you list those names). It keeps the build file machine-agnostic — the *names* are stable, the *paths* vary per runner. ## Where to set them - `~/.gradle/gradle.properties` — per-developer machine, not committed. - Project `gradle.properties` — committed, shared (use `fromEnv` here so paths aren't hardcoded). - `-Dorg.gradle.java.installations.paths=...` on the command line — one-off / CI override. ## Interaction with detection These properties **add to** detection; they don't disable it. The combined set is probed once and cached. If you want *only* the explicit paths (deterministic CI), pair them with `org.gradle.java.installations.auto-detect=false`. Invalid entries (typo'd path, not a JDK) are skipped with a log warning — they don't fail the build, which can mask a misconfiguration, so verify with `./gradlew javaToolchains`. ## Verifying ```bash ./gradlew -q javaToolchains ``` The `javaToolchains` report lists every JDK Gradle discovered, its source ("Current JVM", "environment variable 'JDK17'", "configured location"...), version, vendor, and whether it satisfies declared toolchains. This is the first diagnostic when a toolchain won't resolve.
- What's the difference between paths and fromEnv?paths lists the JDK home directories directly; fromEnv lists environment-variable *names* whose values are JDK homes. fromEnv keeps committed config machine-agnostic, which is why it's preferred on CI.
- How do you confirm Gradle actually picked up a path you configured?Run ./gradlew javaToolchains — it reports each discovered JDK and its source (configured location, environment variable, current JVM, etc.).
- What happens if a configured path is wrong?Gradle logs a warning and skips it; the build doesn't fail just for that entry, so misconfigurations can be silent until a toolchain fails to resolve.
saying these in an interview costs you the question
- Putting a path value into fromEnv (it expects variable names, not paths).
- Pointing paths at a JRE or the bin/ subdirectory instead of the JDK home root.
- Assuming these properties replace auto-detection — they add to it unless you also set auto-detect=false.