JNI (Java Native Interface): Exception in thread “main” java.lang.UnsatisfiedLinkError: Can’t find dependent libraries
How to fix UnsatisfiedLinkError in JNI
I have never had problems with JNI. In the few situations when I needed it, it just worked. But last week someone asked me for help with his problem. When I tried to reproduce it, I found out that it had spread even to my old JNI programs which worked until 2006!
When running a program that uses a native function the following error occured:
Exception in thread "main" java.lang.UnsatisfiedLinkError: Test.dll: Can't find dependent libraries
It’s obviously a linker problem related to the generation of the .dll file. I have no idea why it occurs now and didn’t occur in the past. Different OS, compiler version, something like that? For some reason both the linker of Visual Studio and the linker of GCC started to think that is was a good idea to replace all method names by some arbitrary name which then cannot be found at runtime.
Fix for GCC
To fix that with GCC, the linker opion --add-stdcall-alias can be used.
gcc -Wl,--add-stdcall-alias -mno-cygwin -shared -I/cygdrive/c/Program\ Files/Java/jdk1.6.0_05/include -I/cygdrive/c/Program\ Files/Java/jdk1.6.0_05/include/win32 -o HelloWorld.dll HelloWorld.c
Fix for Visual C
For Microsoft Visual C Compiler it should theoretically be possible with a linker option as well.
Find out the correct linker option
First compile and link in the usual way that didn’t work. This will create the .dll file which results in the error we are talking about. Then use the dumpbin tool to list the procedure names:
dumpbin HelloWorld.dll /EXPORTS
You will find your procedure name, something like _Java_HelloWorld_print@8. Now try to guess what the name should be. My guess in this case would be Java_HelloWorld_print. This would result in the linker option /EXPORT:Java_HelloWorld_print=_Java_HelloWorld_print@8
Supply the linker option
- Use a
#pragma commentin the source file:#pragma comment(linker, "/EXPORT:Java_HelloWorld_print=_Java_HelloWorld_print@8")
OR
- Split into linking and compiling and provide the option to the linker in the command line, OR
- Supply it to the compiler at the end using
/link:cl -I"C:\Program Files\Java\jdk1.6.0_05\include" -I"c:\Program Files\java\jdk1.6.0_05\include\win32" -MD -LD HelloWorld.c -FeHelloWorld.dll /link /EXPORT:Java_HelloWorld_print=_Java_HelloWorld_print@8
Option 3 is probably the easiest. After that dumpbin will show that now there is an additional procedure with the correct name:
dumpbin HelloWorld.dll /EXPORTS
I even compared it with the working .dll I created with GCC (see above), and it looks the same! But it doesn’t work, still getting the same error!
50 USD through PayPal for a solution and an explanation why the current way doesn’t work even though the procedure name is the same as in the working .dll created with GCC. (Only the first solution gets the price; only valid as long as this text is here.)
No comments yet.