diff --git a/java/cuvs-java/pom.xml b/java/cuvs-java/pom.xml index b3b862d291..988dd579c6 100644 --- a/java/cuvs-java/pom.xml +++ b/java/cuvs-java/pom.xml @@ -184,11 +184,12 @@ 3.4.2 + + true + true true - - com.nvidia.cuvs.examples.CagraExample 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..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 @@ -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,52 @@ import java.nio.file.Path; import java.util.Locale; import java.util.Objects; +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 = readCuVSVersionFromManifest(); + + 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 this Jar Manifest, or null if these are not available + */ + 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; + } + } + static MethodHandle createNativeDatasetBuilder() { try { var lookup = MethodHandles.lookup();