[DISCUSS] Automatic JDK toolchain selection when running JDK is incompatible (4.1.0)

Guillaume Nodet <[email protected]> Mon, 3 Aug 2026 14:18:02 +0200
Newsgroups gmane.comp.jakarta.turbine.maven.devel
Message-ID <CAA66Tpr9ALpykJnBaq-W5koivhUudOsT_+ywK0YfwWbDPJtDeg@mail.gmail.com>
--0000000000004b32a9065823888f
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Hi all,

I've opened a draft PR for a quality-of-life feature in Maven 4.1.0:
automatic JDK toolchain selection when the running JDK cannot compile the
project's declared source/release level.

PR: https://github.com/apache/maven/pull/12633

The problem

When a project declares <maven.compiler.source>6</maven.compiler.source>
(or uses <release>, <targetVersion>, or compiler plugin
<configuration><source>), and you run Maven with JDK 21 =E2=80=94 which dro=
pped
--source 6 support =E2=80=94 the build fails with a cryptic javac error. Th=
e user
has to figure out they need to install a compatible JDK and either
configure toolchains.xml or add the maven-toolchains-plugin to their build.
This is a frequent stumbling block, especially when maintaining older
projects.

The solution

Maven now automatically detects the incompatibility and searches for a
compatible JDK =E2=80=94 first in configured toolchains (toolchains.xml), t=
hen by
lazily discovering JDK installations on the filesystem. If a compatible JDK
is found, it's selected as the compilation toolchain and a warning is
emitted:

[WARNING] Project requires --source 6 which is not supported by JDK 21.
[WARNING] Automatically selected JDK 11 (discovered at
/usr/lib/jvm/java-11) for compilation.


This is a zero-cost feature: the auto-selection logic only runs when the
running JDK genuinely cannot handle the project's source level. Normal
builds are completely unaffected.

Design decisions worth discussing

1. Filesystem discovery =E2=80=94 The discoverer scans well-known locations
(SDKMAN, IntelliJ .jdks/, Gradle, jEnv, JBang, asdf, mise, OS-specific
paths like /usr/lib/jvm). Version is read from the JDK release file =E2=80=
=94 no
java processes are spawned. This is essentially what
maven-toolchains-plugin's ToolchainDiscoverer does, but moved into core and
made lazy. Does this make the plugin's auto-discovery redundant? Should we
deprecate it?

2. Source level detection =E2=80=94 We read the source level from multiple =
places
in priority order: Model 4.1.0 <source><targetVersion>, then
maven.compiler.release/maven.compiler.source properties, then compiler
plugin <configuration><release>/<source>. Is this the right precedence? Are
there other places we should check?

3. "Newest compatible" strategy =E2=80=94 When multiple compatible JDKs are=
 found,
we pick the newest one (highest major version that still supports the
required source level). The rationale is that a newer JDK gives better
performance and diagnostics. Should this be configurable?

4. Compat layer =E2=80=94 The v3 ToolchainManagerFactory bridge now passes =
the
discoverer through, so plugins using the v3 API also benefit. This felt
important for the transition period.

CI is green on all platforms (Linux/macOS/Windows =C3=97 JDK 17/21/25).

Feedback and reviews welcome.

Guillaume

--0000000000004b32a9065823888f--