Sometimes I have to use native libraries (.so libraries under Linux or .dll libraries under Windows) in Java programs. That's where you use the Java Native Interface (JNI). It allows you to call functions implemented in native libraries from Java code. And almost every time I forget to remember how the JVM tries to locate the referenced native libraries.
A caveat when trying to load a JNI library in a Java program is that the Java Virtual Machine does not use the default mechanism of the operating system to locate dynamic libraries. A C/C++ program running on a GNU/Linux based operating system would normally use the dynamic linking loader to load dynamic libraries. To be able to load a dynamic library from within Java, the so-called "Java libary path" must contain the path to the directory of the library. Inside the Java Virtual Machine the Java library path is stored in the java.library.path property (see JavaDoc of java.lang.System class). The Java library path can be set using the appropriate command line option when starting the Java Virtual Machine (e.g. java -Djava.library.path=~/lib HelloJNI).
Under Unix-based operating systems, the content of the LD_LIBRARY_PATH environmental variable is merged with the Java library path. Furthermore the Java library path contains the directories /lib/ and /usr/lib/ per default. According to the Filesystem Hierachy Standard the /lib/ directory should contain essential shared libraries and kernel modules. The /usr/lib/ directory should contain libraries for programming and packages.
When running under Windows the Java library path is merged with the content of the PATH environmental variable.
Naturally, a JNI library can reference other dynamically linked libraries. The Java Virtual Machine will then locate the "initial" JNI library using the Java library path, but the "secondary" libraries are loaded using the default mechanism of the operating system.