2

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.

Community
  • 1
  • 1
smwikipedia
  • 61,609
  • 92
  • 309
  • 482
  • Are you sure the problem is with paths? The error states it cannot find the function, not library – Ivan Aksamentov - Drop Apr 27 '15 at 08:59
  • That error message is quite misleading. Actually, I think it says my DLL depends on `libstdc++-6.dll` and `libstdc++-6.dll` cannot be found. Because once I put it into the JDK bin folder, the issue is gone. – smwikipedia Apr 27 '15 at 10:22

1 Answers1

2

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" );

Community
  • 1
  • 1
Karol Król
  • 3,320
  • 1
  • 34
  • 37
  • Thanks. But your solution is for Java to locate a direct dependent DLL. My scenario is a indirect dependent DLL. That is `My Java application -> DLL -> libstdc++-6.dll`. My scenario is the second step. I think this step should be handled by the Windows. And I thought Windows *should* use the %PATH% as the search path. – smwikipedia Apr 27 '15 at 10:19
  • Maybe @Igo Kegel's answer could help you: http://stackoverflow.com/questions/12566732/java-jni-and-dependent-libraries-on-windows – Karol Król Apr 27 '15 at 10:37
  • Thanks Karol. Your link is a great post to explain the concept. But I have found the root cause of my issue. See my update. – smwikipedia Apr 27 '15 at 14:13
  • @smwikipedia - Requiring modification of the system or user %PATH% variable can be heavy-handed and a source of errors. It can be simpler and safer to install the dependent DLL alongside your application, and load it explicitly with `System.load()` or `System.loadLibrary().` – Andy Thomas Apr 27 '15 at 14:21
  • @AndyThomas Thanks for the reminding. `System.load()` and `System.loadLibrary()` is for Java to load the direct dependent DLLs. In my scenario, it's the indirect DLLs I am having the issue, which is resolved by the Windows. – smwikipedia Apr 28 '15 at 00:59
  • 1
    @smwikipedia - You can also use `System.load()` and `System.loadLibrary()` to load those indirect DLLs. – Andy Thomas Apr 28 '15 at 03:32
  • @AndyThomas I didn't know that could work. So if I did that, I can avoid relying on Windows to implicitly resolve indirect DLL dependency for me? And that way, all I need to care is the `java.library.path` property. Right? – smwikipedia Apr 28 '15 at 04:39
  • 1
    @smwikipedia - Right, if you use `System.loadLibrary()`, all you need configure is the process's `java.library.path` property. If you use `System.load(String filename)`, you don't even need that. – Andy Thomas Apr 28 '15 at 04:45
  • @AndyThomas Many thanks. I just wrote a small test app. And it works like a charm. Really appreciate you telling me this. :) – smwikipedia Apr 28 '15 at 04:54
  • @AndyThomas I am wondering if this is some kind of best practices when using native libraries with Java. – smwikipedia Apr 28 '15 at 05:16
  • Please note that you can't change `"java.library.path"` at runtime with `System.setProperty( "java.library.path", "C:\smth" );`. It will be ignored. – Alexei Osipov Dec 19 '17 at 19:14