<< June 4, 2008 | Home | June 6, 2008 >>

JNI FAQ: UnsatisfiedLinkError

I was asked questions similar to the following one quite a few times recently:

[weiqi@gao] $ java Main
Exception in thread "main" java.lang.UnsatisfiedLinkError: no Foo in java.librar
y.path
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
        at java.lang.Runtime.loadLibrary0(Runtime.java:823)
        at java.lang.System.loadLibrary(System.java:1030)
        at Foo.(Foo.java:3)
        at Main.main(Main.java:3)

This question is most prone to be asked by C++ programmers working in a hybrid C++/JNI/Java environment, usually prefixed with "I'm trying to run our test suite, but am getting the following error. Any ideas?"

Here's my response in a email yesterday, posted here through the "Pull email response up to blog entry" refactoring pattern (the answer is Linux specific, but can be translated to other OSes with minimal effort):

This is the part that trips up people all the time. Look at it this way:

  1. Your Main class uses the Foo class
  2. The Foo class uses the libFoo.so JNI glue library. Foo probably looks like this:
    public class Foo {
        static {
          System.loadLibrary("Foo");
        }
        // ...
      }
  3. The libFoo.so JNI glue library uses underlying C++ *.so libraries

The manner through which java searches for the needed files are different in each scenario:

  1. Java searches for *.class files through the "-cp"/"-classpath" command line switch. If neither are specified on the command line, $CLASSPATH is searched
  2. Java searches for JNI glue *.so files through the "-Djava.library.path" command line switch. If "-Djava.library.path" is not specified, $LD_LIBRARY_PATH is searched, but the /etc/ld.so.conf mechanism is not used
  3. The way a JNI glue library searches for the underlying C++ *.so libraries is not controlled by the Java process at all. This is just a case where one *.so library is linked to other *.so libraries. The normal operating system rules apply ($LD_LIBRARY_PATH, /etc/ld.so.conf, etc.)

So you need "-Djava.library.path=...:/path/to/dir-of-libFoo:..." on your java command line. Or add /path/to/dir-of-libFoo to your $LD_LIBRARY_PATH.

As you can see, it's quite a long winded explanation (like a lot of things Java). And even this is not the most thorough. The key insight is the jump from the highlighted part of the stack trace to the corresponding conclusion #2.

Tags :