Pin Java toolchain to the JDK found by find_package(Java) - #6561
Merged
Conversation
hyoklee
requested review from
bmribler,
brtnfld,
fortnern,
gheber,
glennsong09,
jhendersonHDF,
lrknox,
mattjala and
vchoi-hdfgroup
as code owners
July 24, 2026 00:25
github-actions
Bot
removed request for
gheber,
glennsong09,
jhendersonHDF,
mattjala and
vchoi-hdfgroup
July 24, 2026 00:26
Contributor
Review ChecklistThis PR touches the following areas. Each needs a sign-off
|
HDF5 discovers Java twice, through mechanisms with opposite search
precedence, and never reconciles them:
find_package(Java) in CMakeLists.txt sets Java_JAVA_EXECUTABLE,
Java_JAVAC_EXECUTABLE and Java_VERSION_STRING. FindJava searches
JAVA_HOME via HINTS, which outrank $PATH.
project(HDF5_JAVA C Java) in java/CMakeLists.txt sets
CMAKE_Java_COMPILER/RUNTIME/ARCHIVE. CMakeDetermineJavaCompiler searches
$ENV{JAVA_HOME}/bin only as a PATHS entry, the lowest priority slot,
below $PATH, and ignores the CMake variable JAVA_HOME entirely.
When JAVA_HOME and PATH refer to different JDKs the two diverge, so the
FFM/JNI version gate in java/CMakeLists.txt is evaluated against one JDK
while the code is compiled and tested with another. On macOS both resolve
to the /usr/bin stubs, which re-select a JDK from JAVA_HOME on every
invocation, so javac and java can differ inside a single build and every
Java test fails to load its class files with UnsupportedClassVersionError.
Propagate the probed toolchain before the Java language is enabled, filling
each variable independently. The guard in CMakeDetermineJavaCompiler.cmake
is if(NOT CMAKE_Java_COMPILER) and it closes only after the runtime and
archive lookups, so a caller passing just
-DJAVA_HOME=$JAVA_HOME -DCMAKE_Java_COMPILER=$JAVA_HOME/bin/javac
suppresses the other two lookups entirely and ends up with an empty
CMAKE_Java_RUNTIME and an empty TEST_JAVA in the generated CTest files.
Filling them one at a time keeps an explicit override working while still
completing the toolchain.
Verified two ways. Configuring with PATH -> JDK 11 and JAVA_HOME -> JDK 20
previously reported Java 20 and selected the JNI implementation while
CMAKE_Java_COMPILER, CMAKE_Java_RUNTIME and the generated TEST_JAVA all
pointed at JDK 11; they now all resolve to JDK 20. On macOS 26 arm64 with
JAVA_HOME -> JDK 25 the same build went from 95 failing Java tests to none.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hyoklee
force-pushed
the
fix-java-toolchain-jdk-mismatch
branch
from
July 24, 2026 00:31
124b71f to
923a29e
Compare
lrknox
approved these changes
Aug 4, 2026
jhendersonHDF
left a comment
Collaborator
There was a problem hiding this comment.
Rather than override the CMAKE_Java_XXX variables, we should probably remove Java from the list of languages specified in the Java-specific CMakeLists files and also push down this find_package call into those files. See the last comment on https://gitlab.kitware.com/cmake/cmake/-/work_items/18174. Also, the CMake documentation doesn't list support for Java as a language: https://cmake.org/cmake/help/latest/command/project.html#options.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Close #6559.
Problem
When
HDF5_BUILD_JAVA=ON, HDF5 discovers Java twice, through two CMakemechanisms with opposite search precedence, and never reconciles them:
find_package(Java)inCMakeLists.txt→Java_JAVA_EXECUTABLE,Java_JAVAC_EXECUTABLE,Java_JAR_EXECUTABLE,Java_VERSION_STRINGproject(HDF5_JAVA C Java)injava/CMakeLists.txt→CMAKE_Java_COMPILER,CMAKE_Java_RUNTIME,CMAKE_Java_ARCHIVEFindJava.cmakeputsJAVA_HOMEinHINTS, which outrank$PATH, andhonors both
$ENV{JAVA_HOME}and-DJAVA_HOME=viaCMakeFindJavaCommon.cmake.CMakeDetermineJavaCompiler.cmakeputs$ENV{JAVA_HOME}/bininPATHS, thelowest-priority slot, searched after
$PATH, and ignores the CMake variableJAVA_HOMEentirely.So when
JAVA_HOMEand$PATHname different JDKs, the two diverge. HDF5 thenevaluates the FFM/JNI version gate in
java/CMakeLists.txtagainst one JDK while compiling and testing with another.
This is not macOS-specific. On Windows with
PATH→ JDK 11 andJAVA_HOME→JDK 20, current
developreports:macOS merely makes it lethal rather than latent: both lookups land on the
/usr/binstubs, which are not JDKs but dispatchers that re-select one from$JAVA_HOMEat each invocation.javacandjavacan therefore resolve todifferent JDKs inside a single build, and every Java test dies at class load:
(69 = JDK 25, 65 = JDK 21.)
Fix
Propagate the toolchain from
find_package(Java)before theJavalanguage isenabled, filling each variable independently.
Independently matters. The guard in
CMakeDetermineJavaCompiler.cmakeisif(NOT CMAKE_Java_COMPILER)and it closes only after the runtime and archivelookups, so a caller doing
suppresses the other two lookups entirely and ends up with an empty
CMAKE_Java_RUNTIMEand an emptyTEST_JAVAin the generated CTest files — soctest invokes no JVM at all. Filling the three in one at a time keeps an explicit
override working while still completing the toolchain.
Verification
Windows,
PATH→ JDK 11,JAVA_HOME→ JDK 20: compiler, runtime, archiverand
TEST_JAVAnow all resolve to JDK 20, matching theJava_VERSION_STRINGthat drove the implementation choice.
macOS 26.5.2 arm64 (shared / OpenMPI / Fortran / Java),
JAVA_HOME→ JDK 25:the same build went from 95 failing Java tests to 0.
GitHub
macos-26, three configurations — image-defaultJAVA_HOME;JAVA_HOME→ 25 with only-DCMAKE_Java_COMPILERpassed; andJAVA_HOME→ 25with JDK 21 first on
$PATH— all produce a single-JDK toolchain and 255/255Java tests passing. This includes the
ctest -D ExperimentalConfigurepath,where CMake is re-run in a shell whose
JAVA_HOMEhas reverted to the imagedefault; the pin survives because
-DJAVA_HOME=is a cache entry andCMakeFindJavaCommon.cmakeconsults the CMake variable before$ENV{JAVA_HOME}.Notes
JAVA_HOMEand$PATHalready agree, which is thecommon case; the added block only fills variables that are otherwise unset.
-DCMAKE_Java_COMPILER=/-DCMAKE_Java_RUNTIME=still wins.JAVA_HOMEis unset entirely on macOS,find_package(Java)itself falls through to$PATHand finds/usr/bin/java,so the toolchain is pinned to a stub. It is at least pinned consistently, but
hardening that would mean rejecting
/usr/binruntimes or resolving through/usr/libexec/java_homeat configure time.release_docs/RELEASE.txtentry is included; happy to add one if that iswanted for a build-system fix.