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:
- Your Main class uses the Foo class
- The Foo class uses the libFoo.so JNI glue library. Foo probably looks like this:
public class Foo { static { System.loadLibrary("Foo"); } // ... } - 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:
- Java searches for *.class files through the "-cp"/"-classpath" command line switch. If neither are specified on the command line, $CLASSPATH is searched
- 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
- 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.
Re: JNI FAQ: UnsatisfiedLinkError
Sometimes the library called out in the error line is itself attempting to satisfy a dependency that is not shown anywhere in the error message.
In these cases, I have found the "ldd" command to be useful in the *nix environment for these errors.
Once you have determined that your paths are correct and you just know that's not the error, run "ldd" on the .so in the error line and ensure all the dependencies for this shared library can be found.