The UnsatisfiedLinkError means your Java application tried to load a native library (a .dll on Windows, .so on Linux, or .dylib on macOS) that couldn’t be found. This is usually because the library isn’t in a location the Java Virtual Machine (JVM) knows to look for it, or the library itself is missing a dependency.
Here are the most common reasons this happens and how to fix them:
-
The
java.library.pathis not set correctly or doesn’t include the library’s directory.- Diagnosis: Run
System.getProperty("java.library.path")in a Java program or an interpreter to see what directories the JVM is searching. - Fix: When launching your Java application, set the
java.library.pathsystem property. For example:
This tells the JVM to look injava -Djava.library.path=/path/to/your/native/libs -jar your_app.jar/path/to/your/native/libsfor native libraries. - Why it works: The JVM consults
java.library.pathto find native libraries that are explicitly loaded usingSystem.loadLibrary("libraryName").
- Diagnosis: Run
-
The native library is in a location that should be searched but isn’t being found (e.g., within a JAR file).
- Diagnosis: If your native library is bundled inside a JAR file (e.g.,
my-library.jar!/lib/linux-x64/libmylib.so), you’ll need to extract it. You can manually extract it or use a library designed for this. - Fix: Use a utility or a Java library to extract the native library from its JAR at runtime to a temporary directory, and then load it from there. A common pattern is to use
System.load(extractedPath).// Example using a hypothetical library loader String libraryName = "mylib"; // without the lib prefix and .so/.dll suffix String os = System.getProperty("os.name").toLowerCase(); String arch = System.getProperty("os.arch").toLowerCase(); String libraryFileName; if (os.contains("win")) { libraryFileName = libraryName + ".dll"; } else if (os.contains("mac")) { libraryFileName = "lib" + libraryName + ".dylib"; } else { libraryFileName = "lib" + libraryName + ".so"; } // Construct the path within the JAR String resourcePath = "/lib/" + os + "-" + arch + "/" + libraryFileName; // Extract and load try (InputStream in = YourClass.class.getResourceAsStream(resourcePath)) { if (in == null) { throw new RuntimeException("Native library not found in JAR: " + resourcePath); } File tempLib = File.createTempFile(libraryName, ".tmp"); tempLib.deleteOnExit(); // Clean up temp file on exit try (OutputStream out = new FileOutputStream(tempLib)) { byte[] buffer = new byte[1024]; int read; while ((read = in.read(buffer)) != -1) { out.write(buffer, 0, read); } } System.load(tempLib.getAbsolutePath()); } catch (IOException e) { throw new RuntimeException("Failed to extract or load native library", e); } - Why it works:
System.loadLibraryonly searches directories injava.library.path.System.loadallows you to load a library from an absolute path, which you can create by extracting the library from the JAR to a temporary location.
- Diagnosis: If your native library is bundled inside a JAR file (e.g.,
-
The native library depends on other native libraries that are missing or not found.
- Diagnosis: Use a tool like
lddon Linux/macOS or Dependency Walker on Windows to inspect the native library that failed to load. It will list its dependencies. - Fix: Ensure all dependencies of your native library are installed on the system and are discoverable by the operating system’s dynamic linker. This usually means placing them in standard system library paths (e.g.,
/usr/lib,/usr/local/lib) or setting an environment variable likeLD_LIBRARY_PATHon Linux orDYLD_LIBRARY_PATHon macOS.# On Linux, to add a directory to the search path for dependent libraries export LD_LIBRARY_PATH=/path/to/dependencies:$LD_LIBRARY_PATH java -jar your_app.jar - Why it works: The operating system’s dynamic linker is responsible for finding and loading dependent native libraries.
LD_LIBRARY_PATH(or similar) provides additional directories for this linker to search.
- Diagnosis: Use a tool like
-
Architecture Mismatch (32-bit vs. 64-bit).
- Diagnosis: You’re running a 32-bit JVM trying to load a 64-bit native library, or vice-versa. Check
java -version(which will often indicate 64-Bit Server VM or 32-Bit Server VM) and compare it to the architecture of your native library. - Fix: Ensure your JVM’s architecture matches the native library’s architecture. Either install a 64-bit JVM to run your 64-bit library, or compile/obtain a 32-bit version of the native library to run with your 32-bit JVM.
- Why it works: Native libraries are compiled for specific processor architectures. A JVM running on a particular architecture can only load native code compiled for that same architecture.
- Diagnosis: You’re running a 32-bit JVM trying to load a 64-bit native library, or vice-versa. Check
-
Permissions Issues.
- Diagnosis: The user running the Java application does not have read and execute permissions for the native library file or the directory it resides in.
- Fix: Grant the necessary read and execute permissions to the user or group running the application.
chmod +x /path/to/your/native/libs/libyourlib.so chmod +r /path/to/your/native/libs/libyourlib.so - Why it works: The operating system enforces file permissions. The JVM needs to be able to read the library’s contents and execute its code.
-
Corrupted Native Library File.
- Diagnosis: The native library file itself might be corrupted or incompletely downloaded/copied.
- Fix: Re-download or re-copy the native library file from its original source. Ensure the download completed successfully and the file integrity is not compromised.
- Why it works: A corrupted file cannot be correctly loaded or executed by the system.
The next error you’ll likely encounter if you fix this is a NoSuchMethodError or similar if the native library loaded but the specific functions your Java code is trying to call are not present or have different signatures than expected.