Skip to content

fix(manifest): run Gradle and sbt on a JDK they support - #1665

Draft
Martin Torp (mtorp) wants to merge 2 commits into
v1.xfrom
martin/rea-1043-pick-jdk-per-build
Draft

Martin Torp (mtorp) wants to merge 2 commits into
v1.xfrom
martin/rea-1043-pick-jdk-per-build

Conversation

@mtorp

@mtorp Martin Torp (mtorp) commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Part of REA-1043. Older Gradle and sbt versions refuse to start on newer JDKs. So a machine whose default JDK is newer than the project's pinned build tool fails to generate Socket facts, even when a suitable JDK is installed next to it. Managed reachability scans want to move their default JDK to 25, and Gradle 8 projects are where that breaks. The depscan side is SocketDev/depscan#29251, which installs Temurin 8, 11, 17, 21 and 25 side by side.

When facts generation runs a Gradle wrapper or sbt build, the CLI now reads the version the project pins and checks it against the JDK in JAVA_HOME (or the java on PATH). If the build tool doesn't run on that JDK, the build runs on the newest installed JDK it does run on, and the CLI logs which one:

ℹ Running gradle 8.14.3 on Java 21 at /usr/lib/jvm/temurin-21, since it does not run on Java 25 at /usr/lib/jvm/temurin-25.
  • Versions: the Gradle version comes from gradle/wrapper/gradle-wrapper.properties and the sbt version from project/build.properties. A Gradle on PATH, a custom bin and Maven keep the current JDK.
  • Supported ranges: Gradle follows its compatibility matrix. Gradle 9 needs at least 17. sbt needs 1.3 for Java 17 and 1.9 for Java 21 and 25, which I measured (table below). A version newer than the table knows is allowed on any JDK.
  • Discovery: JDKs are found by their release file in the children of /usr/lib/jvm, /usr/lib64/jvm, /usr/java and /opt/java, in SDKMAN, in ~/.gradle/jdks and ~/.jdks, in macOS JavaVirtualMachines bundles, and through the JAVA_HOME_<release>_<arch> variables GitHub and Azure runners set.
  • What stays the same: a javaHome from socket.json is used as is. If no installed JDK fits, the build runs on the current one, as it did before.

Where each build tool started and resolved a Guava dependency (Temurin in Docker):

Build tool 8 11 17 21 25
Gradle 4.10.3, 5.6.4 ✅ ✅
Gradle 6.9.4 ✅ ❌
Gradle 7.6.4 ✅ ✅ ❌
Gradle 8.5, 8.14.3 ✅ ✅ ❌
Gradle 9.0.0 ❌ ✅ ✅
sbt 0.13.18 ✅ ✅ ✅
sbt 1.2.8 ✅ ❌
sbt 1.3.13, 1.5.8 ✅ ❌ ❌
sbt 1.8.3 ❌ ❌
sbt 1.9.0, 1.9.9, 1.10.11 ✅

Testing: unit tests for version parsing, ranges, discovery and selection use real temp-dir JDK layouts. A run.mts test checks that the spawned build gets the picked JAVA_HOME and that a configured one is kept. End to end, I ran the built CLI in an image with JAVA_HOME set to Temurin 25 and all five JDKs installed. socket manifest gradle on a Gradle 8.14.3 wrapper project ran on 21, and socket manifest scala on an sbt 1.5.8 project ran on 17. Both wrote facts containing the dependency. Without this change both builds fail to start on 25.

Follow-ups, not in this PR:

  • A retry on a recognisable failure, for example a toolchain languageVersion that isn't installed.
  • Per-project JDK hints such as .sdkmanrc, .tool-versions and actions/setup-java.
  • A port to main.

Expected reviewer effort: High-level design decisions

Gradle before 9.1 and sbt before 1.9 do not start on Java 25, and sbt
before 1.3 does not start on Java 17. A machine whose default JDK is
newer than the project's pinned build tool supports therefore failed
to generate Socket facts, even with a suitable JDK installed.

Facts generation now reads the Gradle wrapper or sbt version the
project pins and, when the current JDK is outside the range that
version runs on, runs the build on the newest installed JDK inside it.
Installed JDKs are found under the usual JVM directories, SDKMAN,
Gradle- and IDE-provisioned JDKs, macOS bundles, and the
JAVA_HOME_<release>_<arch> variables CI runners set. A javaHome
configured in socket.json still wins, and Maven builds keep the
current JDK.
The Gradle and sbt Java ranges now come from one table and one
function, compared with semver. JDK discovery reads its search
directories and candidates in parallel, and the two test files share
their fake JDK and Gradle wrapper fixtures.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant