Search code examples
javajava-native-interfacejna

JNA UnsatisfiedLinkError - works when I set java.library.path to a bogus value


Using JNA 4.0.0, on Linux, I am trying to load a native library (libmean.so), which is in the lib subdirectory (the library is just a trivial example that calculates the mean of two numbers).

I run the following code (within Eclipse), with -Djna.library.path=lib set in the run configuration.

import com.sun.jna.Library;
import com.sun.jna.Native;

public class Mean {
  public interface MeanLib extends Library {    
    MeanLib INSTANCE = (MeanLib) Native.loadLibrary("mean", MeanLib.class);
    double mean(double a, double b);
  }
  public static void main(String[] args) {          
    double result = MeanLib.INSTANCE.mean(1.0, 3.0);
    System.out.println(result);
  }
}

But this fails with the following exception:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Can't obtain updateLastError method for class com.sun.jna.Native
at com.sun.jna.Native.initIDs(Native Method)
at com.sun.jna.Native.<clinit>(Native.java:139)
at com.sun.jna.examples.Mean$MeanLib.<clinit>(Mean.java:64)
at com.sun.jna.examples.Mean.main(Mean.java:72)

Through trial-and-error, I have discovered that the code starts working if I also set java.library.path.

However, it works regardless of the value of this property. For example, I can set -Djava.library.path=xxxxxxx and it continues to work. An empty value also works.

What is going on?


Solution

  • The root problem is that there is an older version of JNA installed on the system:

    $ dpkg -l | grep -i jna
    ii  libjna-java  3.2.7-4 Dynamic access of native libraries from Java without JNI
    

    JNA starts up by trying to load its bootstrap native library. It searches for this in various places, as described in the documentation.

    The problem is fixed by using the -Djna.nosys=true flag, which forces JNA to load the native library from your jna.jar, not from the system.

    Setting the java.library.path to a nonsense value has a similar side-effect - it overwrites the normal java.library.path, preventing the system version of JNA from being loaded, and falling back on the version from your local jna.jar.

    The debug setting -Djna.debug_load=true is also useful for diagnosing JNA problems.