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 comment
in 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
Edit: According to user comments, the -MD option above is wrong and causes the problem described below. Do not use -MD! See MSDN for further information about the -MD option.
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!
So, I searched a lot, but I found a solution that worked for me. Removing the -MD gives you this:
cl -Ic:\java\include -Ic:\java\include\win32 -LD HelloWorld.c -FeHelloWorld.dll
For me, it worked! For the rest, I can’t speak C++ and I don’t know why it happened.
Thanks Alexandra,
your insight will help many people! This post gets lots of hits every day :-)
Kai
I have a problem creating a simple Java Application that uses JNI to load a dll that prints the mesage “HelloWorld”.
The following stages were succesful:
1. Creating the HelloWorld.java file and compiling it.
2. Using javah -jni to produce HelloWorld.h (a C/C++ header file)
3. Coding the HelloWorld.c file and compiling it to get:
a) HelloWorld.exp, HelloWorld.dll, HelloWorld.lib, HelloWorld.obj
The stage where I am failing:
1. Running the Java program using: java HelloWorld at the command line produces the following error:
Exception in thread “main” java.lang.UnsatisfiedLinkError: HelloWorld.helloWorld
()V
at HelloWorld.helloWorld(Native Method)
at HelloWorld.main(HelloWorld.java:8)
C:\>
For compilation purposes I am using the Microsoft Visual C++ 2008 Express Edition’s command line utility
What could be the problem with my program
Thanks in anticipation of the best help you can offer
Hello,
is that all the error message you get? Delete the .dll, try again. When it is still the same message, then you know more about the problem. Otherwise you know more as well. Win-win.
Kai
Thanks Alexandra, your insight really works.
I got the same problem with Kai. I think it’s not about the procedure name. If you remove the “-MD” option when you link the C file, it can work.
Wow !!
Thanks so much.
This topic helped me getting started with Java -> JNI -> DLL.
Thanks
add option “-Wl,–kill-at”
`–kill-at’
Specifies that when `dlltool’ is creating the
exports file it should not append the string
`@ ‘. These numbers are called
ordinal numbers and they represent another
way of accessing the function in a DLL, other
than by name.
With this the problem will go away sure shot.
just need to build the helloworld.c following way
cl -I c:\Java\jdk1.6.0_01\include -I c:\Java\jdk1.6.0_01\include\win32 -LD HelloWorld.c -FeHelloWorld.dll
Not with -MD option. Java load library functions are not able to load because of -MD option. I think JNI documentations should be updated.
Exception in thread “main” java.lang.UnsatisfiedLinkError: sendechotohost
at NativePing.sendechotohost(Native Method)
at NativePing.getResultForTheHost(NativePing.java:517)
at NativePing.pingHost(NativePing.java:396)
at NativePing.pingHost(NativePing.java:422)
at NativePing.pingHost(NativePing.java:384)
at NativePing.main(NativePing.java:616)
In Linux I am getting this error. Can any one explain….
hello Franklin,
I’d say either the native binary is not found or it doesn’t contain what you need.
Did you compile it with gcc –add-stdcall-alias? Did you check out which functions the binary contains? Did it contain sendechotohost? Is it in the runtime PATH?
Hi ,
I m a Phd student and actually, i have the same problem. just, im working wih netbeans, and it is forbidden to install any other software or any things. I m working on from 3 days and the delevered message is
“run: Exception in thread “main” java.lang.UnsatisfiedLinkError: HelloWorld.print()V
at HelloWorld.print(Native Method)
at HelloWorld.main(HelloWorld.java:4)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)”
I m respecting all the steps, even i tried until now 5 examples and almost the same display error.
So do any one of u have an idea how to resolve this problem
NB: i m working with netbeans 6,9 and with jdk1.6.0_20
Danke
Hello Ben,
I’d say that the .dll is not in the PATH and not in the working directory, or that something is wrong with it (like for example in my case).
It will help to do it without NetBeans, just run from the command line. That’s certainly possible in your environment.
Kai
Hallo
Das ist ok
Vielen danke:)
Hallo again,
Actually, my I m improving with JNI, the current problem is related to more than one variables returning. Since the C++ functions return more than one variables, so please, dis any one of you have an ideas how it is possible to recover from java the result of more than one variable ?
Thanks in advance
I’ ve the same problem
Exception in thread “main” java.lang.UnsatisfiedLinkError: javacsharptest.JavaCSharpTest.display()V
at javacsharptest.JavaCSharpTest.display(Native Method)
at javacsharptest.JavaCSharpTest.main(JavaCSharpTest.java:18)
I’m working with netbeans6.5
I want to know how to run from command line
Please help me
Hello Saw,
this exact problem has been discussed here already.
Hi
I am getting Exception in thread “main” java.lang.UnsatisfiedLinkError:
when i try to run a native method accessing a .dll in a Dynamic web Project
But i am able to the same code successfully in a simple java project.
Can any one help me how to get out of this issue.
Hi, I am trying to make a sample native method to work but not able till now. I need help to understand what I am doing wrong.
This is the example I am following : http://netbeans.org/kb/docs/cnd/beginning-jni-linux.html
The example is for linux, but I am using windows XP ( In the part of including directories I add win32 from java folder, except linux – I hope this is not the problem).
I do everything from the example good, build without errors, except the last build. It gives me this message:
run:
Exception in thread “main” java.lang.UnsatisfiedLinkError: jnidemojava.Main.nativePrint()V
at jnidemojava.Main.nativePrint(Native Method)
at jnidemojava.Main.main(Main.java:20)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
and this is the code in my main method (done as in the example)
…
I am using Netbeans IDE 6.9.1
Please, every help will be appreciated. I am stuck with this samples, try about ten different samples from the net, and still have not been made one of them working … It is important for me to make one of them working because I am new in JNI and reading something like book about it but in the book everything is done in eclipse and to continue with the reading I have to understand how to make the samples there in NetBeans IDE.
Thanks in advance.
Your dll is not in the PATH, or it has been built wrong. Make sure to use the correct options as described in the blog post to build the dll. Analyse your dll with appropriate tools.
I don’t understand what you are doing with the win32.
Because It is a sample for linux, when directories are add, in the sample they are include and linux, but I am using windows XP, so in my java dk there is win32. Could this be a problem?
Plaase, tell me, what’s the difference between shared object and dll? What is best to be used?
My Case is same as gotqn case. I am using the example – “http://netbeans.org/kb/docs/cnd/beginning-jni-linux.html”. I reached till the end but stuck with the exception :
run:
Exception in thread “main” java.lang.UnsatisfiedLinkError: jnidemojava.Main.nativePrint()V
at jnidemojava.Main.nativePrint(Native Method)
at jnidemojava.Main.main(Main.java:22)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
Any help is highly appreciated.
Hey gotqn – I got the Solution.
Right Click Project Folder – Go to Properties -> Click C Compiler -> Tool Option and edit as follows: gcc-3.exe -Wl,–add-stdcall-alias, if you are using gcc-3.exe as compiler or just gcc.exe. You need to append “-Wl,–add-stdcall-alias” to the Compiler Tool Option and it wroked.
Then Clean and Build the Project and use the resultant .dll or .so in the Main.java program. Let me know if it helped:
This resolves the error:
Exception in thread “main” java.lang.UnsatisfiedLinkError: jnidemojava.Main.nativePrint()V
at jnidemojava.Main.nativePrint(Native Method)
at jnidemojava.Main.main(Main.java:22)
I have the same error and can fix it.
I make an JNI example and everithing works fine then I add that code (the same code and the same DLL) to my project and it don’t work it send me the same error that yours.
Then I check that the only modification was that I add the package instruction in my java code. I google it and see that I need to change the name of all my C methods to contain the new path of mi java files. You can use:
javah -jni MiJavaClass
and compare the generated .h file with your actual C code and if it is differente change it and create the new DLL and try to access it.
Thanks for all the members in this post….
If you are using gcc complier, then add “-Wl,-kill-at” as one of the argument to gcc, This will solve the problem.
So, for example, in my case the command looks like this
“-Wl,-kill-at” -shared HelloWorld.c “-Ic:\Program Files\Java\jdk1.6.0_02\include” “-Ic:\Program Files\Java\jdk1.6.0_02\include\win32” -o ${workspace_loc:/JNISampleJava/bin}\HelloWorld.dll
Idk if this will help anyone, but I’m using C++ compiling with VS win64 2010 command prompt.
I used the -MD option suggested fix and it did not affect my link problem.
I since my code was written in C++ I had modified my JNI header file code and removed this code:
“#ifdef __cplusplus
extern “C” {
#endif
//Method prototypes
#ifdef __cplusplus
}
#endif”
Obviously I’m not very clever. Once I put this code back in and ran the dumpbin tool (thanks to whoever mentioned that first) I got a perfect looking signatures.
This solved my linking issue.
I have a probable solution for anyone getting this error when working with Eclipse! If you are loading your dll file as a resource into your system classloader, then you absolutely must do a project–>clean every single time you update your dll!! Even restarting eclipse or your computer won’t clear the old dll resource from your classloader. Tracking that one down was incredibly painful!
Thanks Alexandra,
Yes, removing the -MD make it work for me! I am sure you know why by now. Could you pl. share it in this forum?
Regards … Hari
Alexandra Niculai and degree are correct, deleting the -MD from the command works perfect thank you.
Nice tutorial and thanks for sharing information. I have also share my view as How to fix java.lang.unsatisfiedLinkError in java let me know how do you find it.
thanks a lot
i generate .dll files using GCC but it’s create problem like
java.lang.UnsatisfiedLinkError
But then i used TCC (Tiny C compiler ) and generate .dll and it’s works for me……..
All thanks to you, i am able to run my first jni java after 11 years working in java & i used to give up in between and never used to work so hard to look for solution and used to stick with java alone.
Thanks to you solution
-Wl,–add-stdcall-alias -mno-cygwin
It did the all the magic, thanks for this kind blog.
-Wl, –kill-at OR -Wl,–add-stdcall-alias worked for me
Thank you SO much for your help kai W
[…] 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 […]