java-native-access/jna · critical · java.lang.UnsatisfiedLinkError
UnsatisfiedLinkError(e.getMessage())
Error message
UnsatisfiedLinkError(e.getMessage())
What it means
During loadNativeLibrary, after successfully System.load-ing the extracted jnidispatch library, JNA attempts cleanup (deleteLibrary) of the temporary file; an IOException raised inside this try block is rethrown as UnsatisfiedLinkError with the original IOException message. The native library load itself is wrapped here, so a genuine load failure with a textual reason also surfaces this way.
Source
Thrown at src/com/sun/jna/Native.java:1124
}
LOG.log(DEBUG_JNA_LOAD_LEVEL, "Trying {0}", lib.getAbsolutePath());
System.setProperty("jnidispatch.path", lib.getAbsolutePath());
System.load(lib.getAbsolutePath());
jnidispatchPath = lib.getAbsolutePath();
LOG.log(DEBUG_JNA_LOAD_LEVEL, "Found jnidispatch at {0}", jnidispatchPath);
// Attempt to delete immediately once jnidispatch is successfully
// loaded. This avoids the complexity of trying to do so on "exit",
// which point can vary under different circumstances (native
// compilation, dynamically loaded modules, normal application, etc).
if (isUnpacked(lib)
&& !Boolean.getBoolean("jnidispatch.preserve")) {
deleteLibrary(lib);
}
}
catch(IOException e) {
throw new UnsatisfiedLinkError(e.getMessage());
}
}
/** Identify temporary files unpacked from classpath jar files. */
static boolean isUnpacked(File file) {
return file.getName().startsWith(JNA_TMPLIB_PREFIX);
}
/** Attempt to extract a native library from the current resource path,
* using the current thread context class loader.
* @param name Base name of native library to extract. May also be an
* absolute resource path (i.e. starts with "/"), in which case the
* no transformations of the library name are performed. If only the base
* name is given, the resource path is attempted both with and without
* {@link Platform#RESOURCE_PREFIX}, after mapping the library name via
* {@link NativeLibrary#mapSharedLibraryName(String)}.
* @return File indicating extracted resource on disk
* @throws IOException if resource not foundView on GitHub (pinned to d036ad9781)
Solutions
- Read the embedded message (e.getMessage()) for the true cause - typically 'wrong ELF class' or a missing dependent library
- Match JVM bitness with the bundled native library (use a full official jna.jar for the platform)
- Set -Djna.tmpdir to a writable directory with space, or -Djnidispatch.preserve=true to keep the extracted file for diagnosis
- Run ldd/otool on the extracted libjnidispatch to find missing OS dependencies and install them
Example fix
// before
catch(IOException e) { /* silently lost */ }
// after
try { /* ensure writable temp */ Files.createDirectories(Paths.get(System.getProperty("jna.tmpdir", "/var/tmp/app"))); } catch (IOException e) { throw new RuntimeException("jna.tmpdir not writable: " + e.getMessage(), e); } Defensive patterns
Strategy: try-catch
Validate before calling
// pre-checks before first JNA call
String arch = System.getProperty("os.arch");
boolean jvm64 = System.getProperty("sun.arch.data.model", "64").equals("64");
if (!jvm64 && arch.contains("64")) throw new IllegalStateException("32-bit JVM with 64-bit natives likely - match bitness"); Try / catch
try { Native.load("c", CLibrary.class); } catch (UnsatisfiedLinkError e) { String m = String.valueOf(e.getMessage()); if (m.contains("wrong ELF class") || m.contains("Can't load library") || m.contains("unable to load library")) { throw new IllegalStateException("jnidispatch load failed: " + m + " - check bitness/OS deps", e); } throw e; } Prevention
- Match JVM and native library bitness
- Install OS dependencies jnidispatch requires (glibc, libffi on older systems)
- Set a writable jna.tmpdir and consider -Djnidispatch.preserve=true when debugging
When it happens
Trigger: System.load failing on the extracted library (wrong architecture, missing dependent shared objects, corrupt file) or an IOException during post-load temporary-file handling in loadNativeLibrary.
Common situations: Copying a 64-bit JRE onto a 32-bit libjnidispatch (or vice versa); running where required OS dependencies of jnidispatch are absent; read-only or full temp dirs causing I/O errors during unpack handling.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Unable to locate JNA native support library
- No trash location found (define fileutils.trash to be the pa
- Could not find JNA native support
- Native library (resourcePath) not found in resource path (pa
- File URL url could not be properly decoded
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/993969160b1008ee.
Report an issue: GitHub.