Reputation: 57202
I'm running a library via JNI (I didn't write it), and internally it calls another DLL. I get an error saying "Can't find dependent libraries" unless I put the path of the other DLL on the system PATH variable (I'm on Windows XP). I'd like to be able to handle this on the java command line, and I've already tried adding it to -Djava.library.path
and to the classpath, neither which worked (I expected -Djava.library.path
to work but not classpath, but neither worked). Is there a way to do this?
Upvotes: 19
Views: 39004
Reputation: 1498
I had a similar problem. My requirement was to load the following library in a windows environment:
System.loadLibrary("ibex-java");
In my case, I had configured the -Djava.library.path=C:\projetos\platform\windows\ibex
to a folder where all required dlls were stored.
C:\projetos\platform\windows\ibex>dir
21/08/2020 14:49 <DIR> .
21/08/2020 14:49 <DIR> ..
21/08/2020 07:47 <DIR> ibex
21/08/2020 14:49 128.108 ibex-java.dll
21/08/2020 14:49 8.554 ibex-java.dll.a
21/08/2020 14:49 6.582.641 ibex.dll
21/08/2020 14:49 5.577.792 ibex.dll.a
21/08/2020 07:47 938.157 libgcc_s_dw2-1.dll
21/08/2020 14:49 6.349.752 libibex.a
21/08/2020 07:47 1.508.122 libstdc++-6.dll
However when I tried to load this library the following error was thrown:
Caused by: java.lang.UnsatisfiedLinkError: C:\platform\windows\ibex\ibex-java.dll: Can't find dependent libraries
As we can see, all dependent dlls are in the same folder of the library path. However, the single line System.loadLibrary("ibex-java");
couldn't automatically load them. One option to solve this problem was to put the library path in the PATH
environment variable of windows, but I didn't like this idea.
In my case I find a better solution, find the DLLs dependencies and load these libraries by-hand. For example:
System.loadLibrary("libgcc_s_dw2-1");
System.loadLibrary("libstdc++-6");
System.loadLibrary("ibex");
System.loadLibrary("ibex-java");
Upvotes: 0
Reputation: 1092
For me, making a static build worked, which compiles with:
g++ -static
It adds the dependent libraries in the build itself.
Upvotes: 1
Reputation: 21
This helped me a lot. Also managed loading a JNI dll built using cygwin:
first:
/* conditioned if OS is windows because also need it to work in Linux env. */
System.loadLibrary("cygwin1");
then:
System.loadLibrary("mylib");
On windows, This requires either setting the java.library.path to match both libraries locations.
If runnning from Eclipse, this setting may be replaced by "Native Libraries Location" in java build path (in JRE libraries settings).
However, still finding this a bit tricky.
Upvotes: 2
Reputation: 2033
I've successfully injected a folder into the PATH variable using JNA. This can be used as a workaround if you want to deploy your dependent DLLs alongside your application without tainting the global environment or messing with explicit DLL load order.
However it's not clear to me how the classloader lifecycle affects this. I've only tried this technique under the NetBeans module system, but if you look through the ClassLoader class code for loadLibrary, you'll see that it caches some path variables. It may or may not be necessary to create a new classloader to load the library on.
The downside is you need to use JNA or JNI. Also, it seems like a pretty gross hack. See here for an example of how to set an environment variable using JNA.
Upvotes: 0
Reputation: 10732
I was able to get this to work without putting any DLLs on the PATH by using System.load() on all DLLs in reverse dependency order. Just to be clear, I was calling System.load() on all dependent DLLs, not just JNI DLLs. You don't have to call System.load() on DLLs that come with Windows (they're on the PATH).
I was doing this in a web app where a jar included DLLs that were getting unpacked. Your situation seems simpler, so I believe it should work. I generally followed the solution here: How to make a JAR file that includes DLL files?
Upvotes: 9
Reputation: 16518
Upvotes: 19