101

I'm working on a Java project that uses the JNI. The JNI calls a custom library that I've written myself, let's say mylib.dll, and that depends on a 3rd party library, libsndfile-1.dll.

When I run my program it crashes with

java.lang.UnsatisfiedLinkError:  C:\...path...\mylib.dll: Can't find dependent libraries.

I've searched this site (and others) and I've tried a number of fixes:

  1. I ran dependency walker. DW gave a couple of warnings -- that two libraries required by libsndfile, MPR.DLL and SHLWAPI.DLL, had "unresolved imports" -- but the DW FAQ said that these warnings could be safely ignored.

  2. I fixed the method names in mylib.dll, as suggested here. The method names had somehow gotten mangled by the compiler, but I added linker flags and the dll method names now match those in my jni header file exactly.

  3. I put all of these DLLs in the same directory -- the same directory as the .jar that calls them -- to ensure that they're on the right PATH.

No dice.

Does anyone have any idea what's going on?

I'm doing my development in Visual Studio 2010 on a MacBook pro (via Parallels). I'm doing my testing in Windows XP on a toshiba laptop.

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
dB'
  • 7,838
  • 15
  • 58
  • 101
  • 1
    have you set -Djava.library.path ? – Jochen Bedersdorfer May 23 '11 at 02:41
  • 1
    I haven't, actually, because I'm not launching the program from the command line. I'm writing a library for Processing (processing.org), and Processing is responsible for launching my code. I've checked the java library path at runtime, though, and the folder containing my DLLs is on it. – dB' May 23 '11 at 03:02
  • As I said, all the DLLs are in the same folder, next to my .jar file. So I don't think the problem is that they're not on the path. But thanks anyway. – dB' May 23 '11 at 03:05
  • 7
    On Windows we've had to put .dll files in the [JRE]\bin directory (same place where java.exe, etc. are) to get Java to see them automatically without having to muck with command line options or environment variables. – QuantumMechanic May 23 '11 at 03:28
  • 4
    Hmm... ok, I tried putting all my .dlls in [JRE]\bin. This works! – dB' May 23 '11 at 06:28
  • 1
    See where `.` is in your `PATH`, relative to other directories (JRE, Windows, etc...). One of the earlier entries might be providing a version of a library that's incompatible with the ones you're trying to load from the current directory. Moving `.` ahead in my PATH did the trick for me, and saved me from having to pollute the JRE directory with my libraries. – Kyle Krull Dec 24 '14 at 18:16
  • No matter how hard you look at paths etc, if you don't have the proper ms redist installed to match the toolchain you built with, you may still see unresolved deps; so just be aware of that. – Paul Gregoire Jul 28 '20 at 14:50

18 Answers18

62

I'm pretty sure the classpath and the shared library search path have little to do with each other. According to The JNI Book (which admittedly is old), on Windows if you do not use the java.library.path system property, the DLL needs to be in the current working directory or in a directory listed in the Windows PATH environment variable.


Update:

Looks like Oracle has removed the PDF from its website. I've updated the link above to point to an instance of the PDF living at University of Texas - Arlington.

Also, you can also read Oracle's HTML version of the JNI Specification. That lives in the Java 8 section of the Java website and so hopefully will be around for a while.


Update 2:

At least in Java 8 (I haven't checked earlier versions) you can do:

java -XshowSettings:properties -version

to find the shared library search path. Look for the value of the java.library.path property in that output.

QuantumMechanic
  • 13,795
  • 4
  • 45
  • 66
  • 2
    Yeah, `CLASSPATH` is not used at all. I'm not sure the `cwd` is used at all, either. `java.library.path` or simply `PATH` will work. @dB', the place where you've got them now is *wrong*. – Ernest Friedman-Hill May 23 '11 at 03:41
  • 1
    Thanks so much guys! I think part of the problem here was a confusion on my part between the Windows PATH environment variable, java.library.path and the java CLASSPATH. It all makes more sense now. – dB' May 23 '11 at 06:26
  • Please can you explain how did you overcome through this problem? – SL_User Jun 16 '12 at 11:48
  • 6
    @SL_User I think if you add the directory where the libraries are to the environment variable "path" and restart the command prompt or terminal it should fix it. Java looks for jars under classpath, and libraries under path. – xxjjnn Feb 02 '13 at 17:40
  • 1
    Based on this answer, it looks like that command for Update 2 has been available since at least Java 7: http://stackoverflow.com/a/8472139/901641 – ArtOfWarfare Sep 30 '16 at 15:59
23

I want to inform this interesting case, after tried all the above method, the error is still there. The weird thing is it works on a Windows 7 computer, but on Windows XP it is not. Then I use dependency walker and found on the Windows XP there is no VC++ Runtime as my dll requirement. After installing VC++ Runtime package here it works like a charm. The thing that disturbed me is it keeps telling Can't find dependent libraries, while intuitively the JNI dependent dll is there, however it finally turns out the JNI dependent dll requires another dependent dl. I hope this helps.

rushi
  • 142
  • 1
  • 12
longbkit
  • 1,218
  • 1
  • 13
  • 20
  • 5
    The message is correct albeit misleading in this case. I had both VC++ runtimes missing on the test box and the library compiled in the debug mode (depending on *non*-redistributable debug runtimes). [Dependency Walker](http://www.dependencywalker.com/) was a great help to figure this one out. – Johnny Baloney Sep 21 '14 at 16:27
  • had the same issue using jnetpcap-library. the dependency winpcap wasn't installed on the machine anymore and the exception message was misleading – BlackFlag Sep 03 '18 at 09:41
  • im thinking this might be my case . – I.Tyger Mar 17 '19 at 12:22
  • These days, dependency walker is getting pretty "long in the tooth". It couldn't open a recent windows 10/64-bit dll at all, so I still have no idea which library is missing... Whee. – Mark Storer Sep 04 '19 at 17:07
  • Dependency Walker has a modern replacement: https://github.com/lucasg/Dependencies – Bombe Aug 03 '21 at 12:38
15

You need to load your JNI library.

System.loadLibrary loads the DLL from the JVM path (JDK bin path).

If you want to load an explicit file with a path, use System.load()

See also: Difference between System.load() and System.loadLibrary in Java

Community
  • 1
  • 1
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
  • No, if java.library.path is set, System.loadLibrary loads the DLL from there - but not the dependent libraries https://bugs.openjdk.org/browse/JDK-8213772 – Falco Preiseni Jan 27 '23 at 17:33
12

If you load a 32 bit version of your dll with a 64 bit JRE you could have this issue. This was my case.

EFalco
  • 668
  • 1
  • 8
  • 11
  • This is most likely also my case; if someone is aware of known workarounds I'd be interested; except loading a 64 bit version, as in this case the process is not a dll but `chromedriver.exe`, the Selenium driver for Chrome, which as far as I can tell only comes in 32 bit version. – SantiBailors Dec 16 '16 at 10:31
5

Did have identical problem with on XP machine when installing javacv and opencv in combination with Eclipse. It turned out that I was missing the following files:

  • msvcp100.dll
  • msvcr100.dll

Once these were installed, the project compiled and ran OK.

Community
  • 1
  • 1
5

Please verify your library path is right or not. Of course, you can use following code to check your library path path: System.out.println(System.getProperty("java.library.path"));

You can appoint the java.library.path when launching a Java application:

java -Djava.library.path=path ...
hoat4
  • 1,182
  • 12
  • 9
caopeng
  • 914
  • 13
  • 23
5

When calling System.loadLibrary(), the JVM will look on the java.library.path for your native library. However, if that native library declares any dependencies on other native libraries, then the operating system will be tasked with finding those native library dependencies.

Since the operating system has no concept of the java.library.path, it will not see any directories you place on the java.library.path. Instead, it will only search the directories on PATH environment variable of the operating system. This is totally fine if the native library dependency is an operating system native library because it will be found on the PATH. However, if the native library dependency is a native library that you or someone else created, then it will not be found on the PATH unless you place it there. This behavior is strange, unexpected, and not well documented, but it is documented in the OpenJDK issue tracker here. You can also find another StackOverflow answer reinforcing this explanation, here.

So, you have a couple of options. You could either load each native library in the correct dependency order using System.loadLibrary(), or you could modify the PATH to include the directories where your native libraries are stored.

  • 1
    That helped me to understand how lib are searched from OS perspective. My issue was when I loaded (by System loadLibrary) tibrvj i got the error of not finding dependent libraries. Appending %TIBRV_HOME%/lib to PATH (even through Run Configuration) fixed the issue. Thanks – 27P Mar 15 '21 at 12:38
2
  • Short answer: for "can't find dependent library" error, check your $PATH (corresponds to bullet point #3 below)
  • Long answer:
    1. Pure java world: jvm uses "Classpath" to find class files
    2. JNI world (java/native boundary): jvm uses "java.library.path" (which defaults to $PATH) to find dlls
    3. pure native world: native code uses $PATH to load other dlls
user2038596
  • 535
  • 1
  • 3
  • 14
2

I found a great article by some friends at keepsafe that went through the same thing I did. It worked for me, so hopefully it helps you out as well! Have a read if you're interested (The Perils of Loading Native Libraries on Android) or just use

compile 'com.getkeepsafe.relinker:relinker:1.2.3'

and replace

System.loadLibrary("myLibrary");

with

ReLinker.loadLibrary(context, "mylibrary");
rhysl
  • 33
  • 5
2

installing Microsoft Visual C++ 2010 SP1 Redistributable Fixed it

  • In addition , do verify your system whether it is x64 or x86 and download the appropriate version from [here](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-160) – Nitin Bisht Oct 05 '21 at 10:26
1

I had the same issue, and I tried everything what is posted here to fix it but none worked for me. In my case I'm using Cygwin to compile the dll. It seems that JVM tries to find the JRE DLLs in the virtual Cygwin path. I added the the Cygwin's virtual directory path to JRE's DLLs and it works now. I did something like:

SET PATH="/cygdrive/c/Program Files/Java/jdk1.8.0_45";%PATH%

estebanuri
  • 848
  • 1
  • 10
  • 11
1

In my situation, I was trying to run a java web service in Tomcat 7 via a connector in Eclipse. The app ran well when I deployed the war file to an instance of Tomcat 7 on my laptop. The app requires a jdbc type 2 driver for "IBM DB2 9.5". For some odd reason the connector in Eclispe could not see or use the paths in the IBM DB2 environment variables, to reach the dll files installed on my laptop as the jcc client. The error message either stated that it failed to find the db2jcct2 dll file or it failed to find the dependent libraries for that dll file. Ultimately, I deleted the connector and rebuilt it. Then it worked properly. I'm adding this solution here as documentation, because I failed to find this specific solution anywhere else.

bwfrieds
  • 341
  • 3
  • 20
1

I used to have exactly the same problem, and finally it was solved.

I put all the dependent DLLs into the same folder where mylib.dll was stored and make sure the JAVA Compiler could find it (if there is no mylib.dll in the compilation path, there would be an error reporting this during compiling). The important thing you need to notice is you must make sure all the dependent libs are of the same version with mylib.dll, for example if your mylib.dll is release version then you should also put the release version of all its dependent libs there.

Hope this could help others who have encountered the same problem.

0

Creating static library worked for me, compiling using g++ -static. It bundles the dependent libraries along with the build.

Caesar
  • 1,092
  • 12
  • 19
0

place the required dlls in folder and set the folder path in PATH environment variable. make sure updated environment PATH variable is reflected.

0

I was facing same issue with ffmpeg library after merging two Android projects as one project.

Actually issue was arriving due to two different versions of ffmpeg library but they were loaded with same names in memory. One library was placed in JNiLibs while other was inside another library used as module. I was not able to modify the code of module as it was readonly so I renamed the one used in my own code to ffmpegCamera and loaded it in memory with same name.

System.loadLibrary("ffmpegCamera");

This resolved the issue and now both versions of libraries are loading well as separate name and process id in memory.

Mohsin Raza
  • 488
  • 1
  • 6
  • 12
0

I faced the same problem after migrating my CI into a new machine. I was still facing it even after applying all the above solutions.

The problem was in my new machine, there was Microsoft Visual C++ 2010 SP1 Redistributable x86 installed in it. But my new machine was having 64-bit CPU and operating system. So the fix was that i just updated and installed the 64 bit version from here .

Nitin Bisht
  • 219
  • 1
  • 3
  • 14
-2
  1. Go to http://tess4j.sourceforge.net/usage.html and click on Visual C++ Redistributable for VS2012
  2. Download it and run VSU_4\vcredist_x64.exe or VSU_4\vcredist_x84.exe depending upon your system configuration
  3. Put your dll files inside the lib folder, along with your other libraries (eg \lib\win32-x86\your dll files).
seinecle
  • 10,118
  • 14
  • 61
  • 120