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:

  1. The java.library.path is 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.path system property. For example:
      java -Djava.library.path=/path/to/your/native/libs -jar your_app.jar
      
      This tells the JVM to look in /path/to/your/native/libs for native libraries.
    • Why it works: The JVM consults java.library.path to find native libraries that are explicitly loaded using System.loadLibrary("libraryName").
  2. 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.loadLibrary only searches directories in java.library.path. System.load allows you to load a library from an absolute path, which you can create by extracting the library from the JAR to a temporary location.
  3. The native library depends on other native libraries that are missing or not found.

    • Diagnosis: Use a tool like ldd on 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 like LD_LIBRARY_PATH on Linux or DYLD_LIBRARY_PATH on 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.
  4. 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.
  5. 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.
  6. 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.

Want structured learning?

Take the full Java course →