Long story short: I have an executable jar, that calls jni.dll
which is dependent on lib.dll
. And I'm getting the oh-so-dreaded UnsatisfiedLinkError
.
This answer comes pretty close, yet it fails to solve the problem, from my experience. Even when the folder where the dll's reside is specified in java.library.path
, it will not work. I have to change the Windows PATH
environment variable as well. In fact, the default java.library.path
on Windows seems to be PATH
.
Is there any "pretty" way to fix this? I want to build an installer for Windows and I'm wondering how I would deal with this issue, so that the end-user will not have to do any manual work.
EDIT:
What I implemented is the following: the application ships with a folder called "native_libs" which has dynamic libraries for all supported architectures. The structure is the following:
/
+- native_libs/
+- windows/
| +- x86/
| | +- ...
| +- x64/
| +- ...
|
+- linux/
| +- x86/
| | +- ...
| +- x64/
| +- ...
|
+- libs/
+- ...
On runtime, while the application initializes, the correct JRE architecture and System OS are detected and the proper library files are copied to the libs/ folder. The java.library.path
is being set on runtime as well using a common hack. Finally, the PATH
environment variable for windows is set using a native launcher.
Any room for improvement? Maybe copying the dll's in the same directory as the jar
file would negate the need for setting the java.library.path
and PATH
variables? I need to investigate loading the dll's with System.load()
as well, which will negate the need to copy files.
Java Native Access (JNA) is a community-developed library that provides Java programs easy access to native shared libraries without using the Java Native Interface (JNI). JNA's design aims to provide native access in a natural way with a minimum of effort. Unlike JNI, no boilerplate or generated glue code is required.
JNI is the Java Native Interface. It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++).
loadLibrary(String filename) method loads the dynamic library with the specified library name. A file containing native code is loaded from the local file system from a place where library files are conventionally obtained. The details of this process are implementation-dependent.
java.library.path
specifies the directories where System.loadLibrary()
looks for the dynamic library file. If you change the java.library.path
system property in your code, it will not have any effect. There are hacks to make Java "forget" the initial value and re-evaluate the contents of the java.library.path
system property.
However, the dependent library is not loaded by Java, it's loaded by Windows. Windows does not care about java.library.path
, it only cares about the PATH
environment variable. Your only option is to adjust PATH
for your Java process. For example, if you start it from a batch file, change the PATH
environment variable right before the java invocation.
The simplest solution is to ensure that all .dlls are in '.' when you execute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With