Jeff Storey
Jeff Storey

Reputation: 57202

JNI dependent libraries

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

Answers (6)

João Pedro Schmitt
João Pedro Schmitt

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

Caesar
Caesar

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

user3448399
user3448399

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

gibbss
gibbss

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

Liron Yahdav
Liron Yahdav

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

Vivek
Vivek

Reputation: 16518

  • If you have a DLL name 'MyNativeDLL.dll' then you should use 'MyNativeDLL' in your LoadLibrary call.
  • Use Dependency Walker to check if there are any files required by MyNativeDLL.dll
  • If there are, include them in the same folder as MyNativeDLL.dll - one you get it working try putting the additional required files in System32 folder.

Upvotes: 19

Related Questions