From 2b6bbce4bf2b028bb7200b500b4d380b12db70e7 Mon Sep 17 00:00:00 2001 From: Rahul Goswami Date: Tue, 14 Jul 2026 01:48:59 -0400 Subject: [PATCH] Preload cudart before cuvs native library load to prevent downstream class load errors --- .../cuvs/spi/NativeDependencyLoader.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/NativeDependencyLoader.java b/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/NativeDependencyLoader.java index 107cf0ad16..2c40a45cf1 100644 --- a/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/NativeDependencyLoader.java +++ b/java/cuvs-java/src/main/java22/com/nvidia/cuvs/spi/NativeDependencyLoader.java @@ -53,6 +53,7 @@ private static boolean jarHasNativeDependencies() { static void loadLibraries() throws ProviderInitializationException { if (!loaded) { try { + preloadCudaRuntime(); LOADER_STRATEGY.loadLibraries(); } finally { loaded = true; @@ -60,6 +61,35 @@ static void loadLibraries() throws ProviderInitializationException { } } + /** + * Best-effort preload of the CUDA runtime (libcudart) into the process before loading + * {@code cuvs_c}. + * + *

Neither the embedded nor the system loader strategy bundles cudart (it is always + * system-loaded, even with the fat jar), so it must be resolvable when {@code cuvs_c} is loaded. + * In some deployments (e.g. cuvs-java embedded in an application that manages the classpath, such + * as Solr) the CUDA runtime is present but not resolved at {@code cuvs_c} load time, which makes + * the first native downcall fail with an unresolved-symbol {@link UnsatisfiedLinkError}. + * Preloading cudart here places its soname in the process so the subsequent {@code cuvs_c} load + * can satisfy its dependency. + * + *

This is intentionally best-effort: any failure is swallowed. If cudart is genuinely required + * but missing, the {@code cuvs_c} load below fails and is surfaced as a + * {@link ProviderInitializationException}, degrading to {@code UnsupportedProvider} — we must not + * pre-empt that graceful path by throwing here. Reasons a preload may fail while the system is + * still usable: cudart is exposed only as a versioned soname ({@code libcudart.so.N}) with no + * unversioned {@code libcudart.so} devel symlink for {@link System#loadLibrary} to find, or it + * was already loaded by another classloader. + */ + private static void preloadCudaRuntime() { + try { + System.loadLibrary("cudart"); + } catch (UnsatisfiedLinkError e) { + // Best-effort: cudart is either genuinely missing (the cuvs_c load below will report it) or + // already loaded / only present as a versioned soname. Either way, continue. + } + } + private static class EmbeddedNativeDependencyLoaderStrategy implements NativeDependencyLoaderStrategy {