| Artifact ID | Java Version | Description | Status | FFM implementation (future default) | Production-ready | +
|---|---|---|---|
| hdf5-native | +Java 8+ | +Platform native libhdf5 bundle loaded via SciJava native-lib-loader | +Optional; add explicitly for bundled libhdf5 | +
| hdf5-zlib-native | +Java 8+ | +Platform zlib bundle used by libhdf5's built-in deflate/GZIP filter | +Optional; add explicitly when shared zlib is enabled | +
| hdf5-szip-native | +Java 8+ | +Platform libaec (libsz + libaec) bundle used by libhdf5's built-in SZIP filter | +Optional; add explicitly when shared libaec (szip) is enabled | +
| hdf5-jni-native | +Java 8+ | +Platform JNI bridge bundle for hdf5-java-jni | +Required transitive dependency of hdf5-java-jni | +
| hdf5-java-examples | Java 8+ | @@ -39,6 +63,10 @@ HDF5 provides three main Maven artifacts:
H5Pset_deflate and through tools as GZIP=level. It is built into libhdf5 when zlib support is enabled; hdf5-zlib-native ships the runtime zlib library needed by that built-in filter when libhdf5 links zlib dynamically. Call H5.loadH5Lib() once at startup; bundled zlib is loaded automatically before libhdf5. No HDF5_PLUGIN_PATH or external HDF5 installation is required for gzip/chunked datasets when using these Maven artifacts.
+
+The HDF5 SZIP filter is exposed through H5Pset_szip and uses the libaec szip-compatible API. It is built into libhdf5 when SZIP support is enabled; hdf5-szip-native ships the runtime libaec/libsz shared libraries needed by that built-in filter when libhdf5 links libaec dynamically.
+
Note: FFM will become the default implementation in the next major HDF5 release.
\subsection subsec_maven_jni Using JNI Implementation (Java 8+)
diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt
index 615914b19a6..dc69282a97d 100644
--- a/java/CMakeLists.txt
+++ b/java/CMakeLists.txt
@@ -8,6 +8,11 @@ include (UseJava)
mark_as_advanced (CMAKE_Java_ARCHIVE)
mark_as_advanced (CMAKE_Java_RUNTIME)
+# Development component provides Java_JAR_EXECUTABLE for native Maven bundles
+if (HDF5_ENABLE_MAVEN_DEPLOY)
+ find_package (Java COMPONENTS Development)
+endif ()
+
if (WIN32)
set (HDF_JRE_DIRECTORY "C:/Program Files/Java/jre")
else ()
@@ -163,6 +168,75 @@ if (Java_VERSION_STRING VERSION_GREATER_EQUAL "25.0.0")
message (FATAL_ERROR "jextract did not generate expected file: ${EXPECTED_FFM_FILE}")
endif ()
+ # Post-process jextract output: vanilla SYMBOL_LOOKUP breaks bundled Maven natives (see
+ # java/cmake/ffm-jextract-hdf5_h_2/README.txt). Needle and replacement live there.
+ set (_HDF5_FFM_JEXTRACT_PATCH_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake/ffm-jextract-hdf5_h_2")
+ set (_HDF5_FFM_JEXTRACT_NEEDLE "${_HDF5_FFM_JEXTRACT_PATCH_DIR}/needle.txt")
+ set (_HDF5_FFM_JEXTRACT_REPLACEMENT "${_HDF5_FFM_JEXTRACT_PATCH_DIR}/replacement.txt")
+ if (NOT EXISTS "${_HDF5_FFM_JEXTRACT_NEEDLE}")
+ message (
+ FATAL_ERROR
+ "FFM jextract post-process needle missing: ${_HDF5_FFM_JEXTRACT_NEEDLE}"
+ )
+ endif ()
+ if (NOT EXISTS "${_HDF5_FFM_JEXTRACT_REPLACEMENT}")
+ message (
+ FATAL_ERROR
+ "FFM jextract post-process replacement missing: ${_HDF5_FFM_JEXTRACT_REPLACEMENT}"
+ )
+ endif ()
+ file (READ "${_HDF5_FFM_JEXTRACT_NEEDLE}" _HDF5_h2_old)
+ string (REPLACE "\r\n" "\n" _HDF5_h2_old "${_HDF5_h2_old}")
+ file (READ "${_HDF5_FFM_JEXTRACT_REPLACEMENT}" _HDF5_h2_new)
+ string (REPLACE "\r\n" "\n" _HDF5_h2_new "${_HDF5_h2_new}")
+
+ set (_HDF5_HDF5_H_2 "")
+ file (
+ GLOB _HDF5_FFM_H2_CANDIDATES
+ "${JEXTRACT_OUTPUT_DIR}/org/hdfgroup/javahdf5/hdf5_h*.java"
+ )
+ foreach (_HDF5_h2_candidate IN LISTS _HDF5_FFM_H2_CANDIDATES)
+ if (NOT EXISTS "${_HDF5_h2_candidate}")
+ continue ()
+ endif ()
+ file (READ "${_HDF5_h2_candidate}" _HDF5_h2_probe)
+ string (REPLACE "\r\n" "\n" _HDF5_h2_probe "${_HDF5_h2_probe}")
+ string (
+ FIND "${_HDF5_h2_probe}"
+ "static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.libraryLookup"
+ _HDF5_h2_has_lookup
+ )
+ if (NOT _HDF5_h2_has_lookup EQUAL -1)
+ set (_HDF5_HDF5_H_2 "${_HDF5_h2_candidate}")
+ break ()
+ endif ()
+ endforeach ()
+ if ("${_HDF5_HDF5_H_2}" STREQUAL "")
+ message (
+ FATAL_ERROR
+ "jextract did not generate a header class with SYMBOL_LOOKUP under "
+ "${JEXTRACT_OUTPUT_DIR}/org/hdfgroup/javahdf5/"
+ )
+ endif ()
+
+ file (READ "${_HDF5_HDF5_H_2}" _HDF5_h2_src)
+ string (FIND "${_HDF5_h2_src}" "HDF5_FFM_NATIVE_LOOKUP" _HDF5_h2_already_patched)
+ if (_HDF5_h2_already_patched EQUAL -1)
+ string (REPLACE "\r\n" "\n" _HDF5_h2_src "${_HDF5_h2_src}")
+ set (_HDF5_h2_out "${_HDF5_h2_src}")
+ string (REPLACE "${_HDF5_h2_old}" "${_HDF5_h2_new}" _HDF5_h2_out "${_HDF5_h2_out}")
+ if ("${_HDF5_h2_out}" STREQUAL "${_HDF5_h2_src}")
+ message (
+ FATAL_ERROR
+ "Post-jextract patch of ${_HDF5_HDF5_H_2} failed (needle not found). "
+ "jextract output may have changed; update needle.txt under "
+ "${_HDF5_FFM_JEXTRACT_PATCH_DIR}."
+ )
+ endif ()
+ message (STATUS "Patched ${_HDF5_HDF5_H_2} using ${_HDF5_FFM_JEXTRACT_NEEDLE}")
+ file (WRITE "${_HDF5_HDF5_H_2}" "${_HDF5_h2_out}")
+ endif ()
+
message (STATUS "FFM bindings generated successfully at ${JEXTRACT_OUTPUT_DIR}")
endif ()
else ()
@@ -218,6 +292,7 @@ install (
${HDF5_JAVA_LOGGING_JAR}
${HDF5_JAVA_LOGGING_NOP_JAR}
${HDF5_JAVA_LOGGING_SIMPLE_JAR}
+ ${HDF5_JAVA_NATIVE_LIB_LOADER_JAR}
DESTINATION ${HDF5_INSTALL_JAR_DIR}
COMPONENT libraries
)
diff --git a/java/cmake/HDF5JavaJavadoc.cmake b/java/cmake/HDF5JavaJavadoc.cmake
new file mode 100644
index 00000000000..6d2b5dd3e39
--- /dev/null
+++ b/java/cmake/HDF5JavaJavadoc.cmake
@@ -0,0 +1,88 @@
+#-----------------------------------------------------------------------------
+# Shared Java javadoc generation for hdf.hdf5lib bindings.
+# Used by FFM and JNI CMakeLists.txt when HDF5_BUILD_DOC is enabled.
+#-----------------------------------------------------------------------------
+
+# Version aligned with java/lib/native-lib-loader-2.5.0.jar and pom.xml.in
+set (HDF5_JAVA_NATIVE_LIB_LOADER_JAVADOC_VERSION "2.5.0")
+set (HDF5_JAVA_NATIVE_LIB_LOADER_JAVADOC_LINK
+ "https://javadoc.io/doc/org.scijava/native-lib-loader/${HDF5_JAVA_NATIVE_LIB_LOADER_JAVADOC_VERSION}/"
+)
+
+function (hdf5_java_add_javadoc_target CLASSPATH_JARS)
+ if (NOT HDF5_BUILD_DOC)
+ return ()
+ endif ()
+ if (TARGET hdf5_java_doc)
+ return ()
+ endif ()
+
+ if (NOT Java_JAVADOC_EXECUTABLE)
+ find_package (Java COMPONENTS Development)
+ if (NOT Java_JAVADOC_EXECUTABLE)
+ message (WARNING "Java javadoc executable not found; skipping hdf5_java_doc target")
+ return ()
+ endif ()
+ endif ()
+
+ set (_javadoc_sources
+ ${HDF5_JAVADOC_HDF_HDF5_CALLBACKS_SOURCES}
+ ${HDF5_JAVADOC_HDF_HDF5_EXCEPTIONS_SOURCES}
+ ${HDF5_JAVADOC_HDF_HDF5_STRUCTS_SOURCES}
+ ${HDF5_JAVADOC_HDF_HDF5_SOURCES}
+ )
+
+ # Callers pass the classpath jars as a CMake list (";"-separated). javadoc
+ # expects the platform-native path separator, which is ":" on Unix-like hosts
+ # and ";" on Windows. Normalize so the jars resolve on every platform.
+ if (CMAKE_HOST_UNIX)
+ string (REPLACE ";" ":" _javadoc_classpath "${CLASSPATH_JARS}")
+ else ()
+ set (_javadoc_classpath "${CLASSPATH_JARS}")
+ endif ()
+
+ set (_javadoc_builddir "${CMAKE_CURRENT_BINARY_DIR}/javadoc/hdf5_java_doc")
+ set (_javadoc_stamp "${_javadoc_builddir}/.javadoc.stamp")
+
+ set (_javadoc_depends
+ ${_javadoc_sources}
+ ${HDF5_JAVA_LOGGING_JAR}
+ ${HDF5_JAVA_NATIVE_LIB_LOADER_JAR}
+ )
+ if (HDF5_JAVAHDF5_JARS)
+ list (APPEND _javadoc_depends ${HDF5_JAVAHDF5_JARS})
+ endif ()
+
+ add_custom_command (
+ OUTPUT "${_javadoc_stamp}"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${_javadoc_builddir}"
+ COMMAND ${Java_JAVADOC_EXECUTABLE}
+ -d "${_javadoc_builddir}"
+ -classpath "${_javadoc_classpath}"
+ -link "${HDF5_JAVA_NATIVE_LIB_LOADER_JAVADOC_LINK}"
+ -tag "defgroup:a:Group:"
+ -tag "ingroup:a:Group:"
+ -tag "ref:a:See:"
+ -overview "${HDF5_SOURCE_DIR}/java/src-jni/hdf/overview.html"
+ -windowtitle "HDF5 Java"
+ -doctitle "