Must I place all dependent DLLs into the JDK's

2019-01-19 07:53发布

问题:

My java application depends on a DLL, and that DLL further depends on libstdc++-6.dll.

I tried to:

  • placed the libstdc++-6.dll in a folder
  • and put the folder in the %PATH%

Then I meet the java.lang.Unsatisfied LinkError: The specified procedure could not be found when launching application from Eclipse.

But if I put the libstdc++-6.dll into the JDK's bin folder, say C:\Java\jdk1.6.0_45_32bit\bin. It works fine.

But I don't want to pollute the JDK folder. I remember windows will search %PATH% to locate dependent DLLs. Why can't I use the %PATH% in this issue?

Update 1

There are 2 different %PATH% environment variables in Windows.

  • User variables
  • System variables

I just accidentally find that:

  • If I put the DLL's folder to User %PATH%, it cannot be found.

  • If I put the DLL's folder to System %PATH%, it works.

Why?

Update 2

Inspired by this thread:System versus user PATH environmental variable...winmerge works only if I add the path to the user PATH

I start to wonder maybe my User %Path% is too long. So I moved the folder path containing my dependent DLL from the end of User %PATH% to the beginning. It works now!

At first, I conclude that one who implemented the Windows' DLL lookup algorithm has some truncation issue. And I almost consider it as another annoying Windows Bug.

But I wrote another Windows application which has similar DLL dependencies to confirm my guess. That application works fine! So I have to review my conclusion.

I checked my User %PATH% entry one by one, and place the folder to each possible location. And finally, I find the root cause.

I have a C:\MinGW\bin entry in User %PATH%, which happens to contain a libstdc++-6.dll (977KB) but unfortunately, which isn't compatible with the one I need (825KB). It only works if I place my folder before MinGW. So it's actually DLL collision during %PATH% resolution.

Now this issue seems resolved. But another one comes up, do I need to switch back and forth if I want to use both my DLL and the MinGW?

Update 3

Please check the comment by @AndyThomas. He mentioned using System.loadLibrary() for both direct and indirect DLLs. This way, all we need to care about is the java.library.path property. I think that's a once-for-all solution.

回答1:

First: put all DLL files you need in the same directory

Then: Load native libs - to do so you have 3 options:

  1. Set VM Options while you run your app.

-Djava.library.path="C:\Your Directory where Dll is present"

Example:

java -Djava.library.path="C:\Your Directory where Dll is present" -jar app.jar

  1. Load specific native library from within the app:

a) Place the directory that contains the file aaa.dll directly under the Java project.

b) And place this line on the top of stack trace of your app: System.loadLibrary("aaa")

  1. Use VM options from within your app:

System.setProperty( "java.library.path", "C:\Your Directory where Dll is present" );



标签: java dll jni