Java UnsatisfiedLinkError: no library in java.library.path
Fix Java UnsatisfiedLinkError by locating native libraries, matching architectures, and setting java.library.path or system load paths.
Symptoms
- java.lang.UnsatisfiedLinkError: no libfoo in java.library.path
- A JNI or native dependency works on one OS but not another
- The error names a library that exists on disk
Possible causes
- The native library is absent from java.library.path
- The library exists but is built for a different architecture
- Transitive native dependencies are missing (often on Linux)
- The library name lacks the platform prefix/suffix libfoo.so vs foo.dll
Diagnosis steps
Print the searched paths
System.out.println(System.getProperty("java.library.path"));Interpretation
The JVM prints exactly where it looks, so you can compare against the library location.
Verify the library file and architecture
file libfoo.soInterpretation
A file reports ELF/Mach-O/PE and the CPU type; a mismatch explains a load failure.
Check transitive dependencies
ldd libfoo.soInterpretation
Missing transitive .so files cause UnsatisfiedLinkError even when libfoo itself is found.
Root cause
UnsatisfiedLinkError occurs when the JVM cannot load a native library via System.loadLibrary. The library may be missing from java.library.path, built for another architecture, or depend on shared objects that are themselves missing — the JVM reports the top-level failure and hides the transitive cause.
Fix
Point java.library.path at the directory containing the library with -Djava.library.path=..., or call System.load with an absolute path. Ship the correct per-platform build, and install missing system dependencies (for example libgomp or libstdc++) on the host. Keep the platform-prefixed file name intact.
Verify the fix
Re-run the JVM with the corrected path; the native call succeeds and the same application starts on every target platform without UnsatisfiedLinkError.
Symptoms
The JVM fails with UnsatisfiedLinkError: no libfoo in java.library.path even though libfoo.so exists. It is frequently platform-specific, breaking on CI or a server while working on a developer machine.
Diagnosis
Print the search path and verify the file:
java -Djava.library.path=/opt/native -jar app.jar
file /opt/native/libfoo.so
ldd /opt/native/libfoo.so | grep "not found"
ldd reveals missing transitive shared objects that the JVM error omits.
Fix
Set the path explicitly or load by absolute path:
System.load("/opt/native/libfoo.so"); // absolute path
// or -Djava.library.path=/opt/native on the command line
Install the missing system packages and ship the correct architecture build.
Verification
Re-run the native call on each target platform; the library loads, the JNI method executes, and ldd reports no “not found” entries.
Packaging Native Dependencies
Shipping native libraries reliably means treating them as platform artifacts. Include one build per OS and architecture in the jar under a resource path, then extract and load the correct one at runtime by detecting os.name and os.arch. Keep the extraction directory writable, since some environments mount the working directory read-only. On Linux, prefer statically linking the native library when possible to avoid chasing transitive .so files across distributions, and document the runtime packages each platform needs so the deployment image can install them before the JVM starts.