If you want to do something in Java, there’s certainly Java library which helps you with to achieve your goal. However, for some stuff (3D rendering, accessing I/O devices) the Java API’s are not enough and you need to interact directly with the target platform. In such cases, you need to use the Java Native Interface and provide a native library. This also means that you need to ship your application with additional native libraries. Here’s where the issues start.
When you use native-libraries, the JVM needs to load those. By default the JVM loads those libraries from a few standard system paths. Of course you don’t want to touch those. The other alternative is to specify an look-up path with the JVM-argument ‘java.library.path’. This works most of the time, but still has its issues! First, it doesn’t work with a simple jar-launcher! In order to specify this JVM-argument, you need to add a launch-script. The second issue has to with packaging your application. Imagine that you ship your application for different OS, like Linux, Windows 32- and 64-Bit etc. The native binaries are named the same, but are actually for different versions. For example there are two versions of ‘coolLibrary.dll’ one for 32-Bit, one for 64-Bit. You cannot have both in the same directory. You somehow need to decide at runtime which one you pick.
So what you want is to be more flexible how to resolve a native library. And you can! Thanks to our friend ClassLoader. Basically you can overwrite the ClassLoader.findLibrary()-method and implement you own resolving strategy. For example:
Of course, this class-loader should be the ‘root’ class loader of your application. This means this class loader should be responsible for loading all application-classes. To do this, I usually create a small ‘boot’-application, which starts the real application. Basically what it does is to instantiate the NativeLibPathClassLoader, pass it the location of the application with dependencies and then load the real application. Not that your ‘real’ application shouldn’t be on the regular class-path. Otherwise everything is loaded by the system class loader:
This is how I start up Java Desktop Applications which need native libraries. It works wonderful and it solves the annoying ‘java.library.path’-path issue.
- Analyzing Dependencies Java
- Black Books