From b6810e37015fad89310bb3594100ef0f027db17c Mon Sep 17 00:00:00 2001 From: ldematte Date: Fri, 5 Sep 2025 12:30:50 +0200 Subject: [PATCH 1/2] Add cuvs version check to JDKProvider --- java/cuvs-java/pom.xml | 17 +++++++ .../nvidia/cuvs/spi/CuVSServiceProvider.java | 6 ++- .../spi/ProviderInitializationException.java | 26 +++++++++++ .../com/nvidia/cuvs/spi/JDKProvider.java | 44 +++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/ProviderInitializationException.java diff --git a/java/cuvs-java/pom.xml b/java/cuvs-java/pom.xml index b3b862d291..07c364ee03 100644 --- a/java/cuvs-java/pom.xml +++ b/java/cuvs-java/pom.xml @@ -62,6 +62,7 @@ 22 UTF-8 UTF-8 + ${project.version} @@ -155,6 +156,22 @@ + + org.codehaus.mojo + properties-maven-plugin + 1.0.0 + + + generate-resources + + write-project-properties + + + ${project.build.outputDirectory}/version.properties + + + + org.apache.maven.plugins maven-assembly-plugin diff --git a/java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/CuVSServiceProvider.java b/java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/CuVSServiceProvider.java index a4a5843adf..ae4c9b083a 100644 --- a/java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/CuVSServiceProvider.java +++ b/java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/CuVSServiceProvider.java @@ -51,8 +51,12 @@ static CuVSProvider builtinProvider() { if (supportedJavaRuntime && supportedOs && supportedArchitecture) { try { var cls = Class.forName("com.nvidia.cuvs.spi.JDKProvider"); - var ctr = MethodHandles.lookup().findConstructor(cls, MethodType.methodType(void.class)); + var ctr = + MethodHandles.lookup() + .findStatic(cls, "create", MethodType.methodType(CuVSProvider.class)); return (CuVSProvider) ctr.invoke(); + } catch (ProviderInitializationException e) { + return new UnsupportedProvider("cannot create JDKProvider: " + e.getMessage()); } catch (Throwable e) { throw new AssertionError(e); } diff --git a/java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/ProviderInitializationException.java b/java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/ProviderInitializationException.java new file mode 100644 index 0000000000..1a6c34a2fd --- /dev/null +++ b/java/cuvs-java/src/main/java/com/nvidia/cuvs/spi/ProviderInitializationException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nvidia.cuvs.spi; + +class ProviderInitializationException extends Exception { + ProviderInitializationException(String message, Throwable cause) { + super(message, cause); + } + + public ProviderInitializationException(String message) { + super(message); + } +} diff --git a/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java b/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java index 0ee0cf1d10..a9128193a9 100644 --- a/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java +++ b/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java @@ -16,10 +16,14 @@ package com.nvidia.cuvs.spi; import static com.nvidia.cuvs.internal.common.Util.*; +import static com.nvidia.cuvs.internal.panama.headers_h.cuvsVersionGet; +import static com.nvidia.cuvs.internal.panama.headers_h.uint16_t; import com.nvidia.cuvs.*; import com.nvidia.cuvs.internal.*; import com.nvidia.cuvs.internal.common.Util; +import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -28,11 +32,51 @@ import java.nio.file.Path; import java.util.Locale; import java.util.Objects; +import java.util.Properties; final class JDKProvider implements CuVSProvider { private static final MethodHandle createNativeDataset$mh = createNativeDatasetBuilder(); + static CuVSProvider create() throws Throwable { + var mavenVersion = readMavenVersionFromPropertiesOrNull(); + + try (var localArena = Arena.ofConfined()) { + var majorPtr = localArena.allocate(uint16_t); + var minorPtr = localArena.allocate(uint16_t); + var patchPtr = localArena.allocate(uint16_t); + checkCuVSError(cuvsVersionGet(majorPtr, minorPtr, patchPtr), "cuvsVersionGet"); + var major = majorPtr.get(uint16_t, 0); + var minor = minorPtr.get(uint16_t, 0); + var patch = patchPtr.get(uint16_t, 0); + + var cuvsVersionString = String.format(Locale.ROOT, "%02d.%02d.%d", major, minor, patch); + if (mavenVersion != null && !cuvsVersionString.equals(mavenVersion)) { + throw new ProviderInitializationException( + String.format( + Locale.ROOT, + "libcuvs_c version mismatch: expected [%s], found [%s]", + mavenVersion, + cuvsVersionString)); + } + } + return new JDKProvider(); + } + + /** + * Read cuvs-java version from Maven generated properties, or null if these are not available + */ + private static String readMavenVersionFromPropertiesOrNull() { + var properties = new Properties(); + + try (var is = JDKProvider.class.getClassLoader().getResourceAsStream("version.properties")) { + properties.load(is); + return properties.getProperty("version"); + } catch (IOException e) { + return null; + } + } + static MethodHandle createNativeDatasetBuilder() { try { var lookup = MethodHandles.lookup(); From 0bafd248aa5fea42839e9a32935880b4e5e0deb5 Mon Sep 17 00:00:00 2001 From: ldematte Date: Mon, 8 Sep 2025 16:12:43 +0200 Subject: [PATCH 2/2] Use Manifest instead of custom property file --- java/cuvs-java/pom.xml | 22 +++---------------- .../com/nvidia/cuvs/spi/JDKProvider.java | 19 ++++++++-------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/java/cuvs-java/pom.xml b/java/cuvs-java/pom.xml index 07c364ee03..988dd579c6 100644 --- a/java/cuvs-java/pom.xml +++ b/java/cuvs-java/pom.xml @@ -62,7 +62,6 @@ 22 UTF-8 UTF-8 - ${project.version} @@ -156,22 +155,6 @@ - - org.codehaus.mojo - properties-maven-plugin - 1.0.0 - - - generate-resources - - write-project-properties - - - ${project.build.outputDirectory}/version.properties - - - - org.apache.maven.plugins maven-assembly-plugin @@ -201,11 +184,12 @@ 3.4.2 + + true + true true - - com.nvidia.cuvs.examples.CagraExample diff --git a/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java b/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java index a9128193a9..fb1a1e7f78 100644 --- a/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java +++ b/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/JDKProvider.java @@ -32,14 +32,15 @@ import java.nio.file.Path; import java.util.Locale; import java.util.Objects; -import java.util.Properties; +import java.util.jar.JarFile; +import java.util.jar.Manifest; final class JDKProvider implements CuVSProvider { private static final MethodHandle createNativeDataset$mh = createNativeDatasetBuilder(); static CuVSProvider create() throws Throwable { - var mavenVersion = readMavenVersionFromPropertiesOrNull(); + var mavenVersion = readCuVSVersionFromManifest(); try (var localArena = Arena.ofConfined()) { var majorPtr = localArena.allocate(uint16_t); @@ -64,14 +65,14 @@ static CuVSProvider create() throws Throwable { } /** - * Read cuvs-java version from Maven generated properties, or null if these are not available + * Read cuvs-java version from this Jar Manifest, or null if these are not available */ - private static String readMavenVersionFromPropertiesOrNull() { - var properties = new Properties(); - - try (var is = JDKProvider.class.getClassLoader().getResourceAsStream("version.properties")) { - properties.load(is); - return properties.getProperty("version"); + private static String readCuVSVersionFromManifest() { + try (var jarFile = + new JarFile( + JDKProvider.class.getProtectionDomain().getCodeSource().getLocation().getPath())) { + Manifest manifest = jarFile.getManifest(); + return manifest.getMainAttributes().getValue("Implementation-Version"); } catch (IOException e) { return null; }