Solved

Java Native methods giving "java.lang.UnsatisfiedLinkError" for matching parameters

Posted on 2014-02-17
20
1,774 Views
Last Modified: 2014-02-21
I have created dll with C++ code successfully and put the dll in the jdk/bin folder in windows environment.

When I execute the native method it gives Runtime error

 
Exception in thread "main" java.lang.UnsatisfiedLinkError: TestJNI.jgd_function()V
        at TestJNI.jgd_function(Native Method)
        at Test.jgd_function(FedExTest.java:12)
        at main.main(main.java:5)

Open in new window


It is not due to mismatch of the parameters as I passed empty parameters and returned void (even then it gives this error).
0
Comment
Question by:jgdvishnu
  • 8
  • 4
  • 3
  • +2
20 Comments
 
LVL 86

Assisted Solution

by:jkr
jkr earned 250 total points
ID: 39865912
Chances are that C++ name decoration (http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B) is the culprit, 'UnsatisfiedLinkError' also points to that. Open the DLL with the Dependency Walker (www.depends.com) and check the names of the exported functions. If you find that they are different (e.g. a function called 'test' is listed as 'test@V') change your function declaration to be inside a

extern "C" {

  // declarations here
};

Open in new window


block and rebuild your DLL. That should solve the issue.
0
 

Author Comment

by:jgdvishnu
ID: 39866310
1) To avoid name decoration I turned to pure "C" coding (example in SWIG )

2) Dependency Walker shows change in function name slightly.
a) function with void parameter changed to     function@8
Dependency Walker with No Input and void Outputb) function with int parameter changed to     function@12
Dependency Walker with Integer Input and Integer Outputbut Not sure if that is the issue.

3) Changes like these did not help much -

extern "C" {
  int jgdfunction(int i);
};

Or
extern int fact(int n);


Still the stack trace looks like:-


C:\Program Files (x86)\Java\jdk1.6.0_31\bin>java NativeClient
start Loading native method
End of loading native method
start Calling native method
Exception in thread "main" java.lang.UnsatisfiedLinkError:  TestJNI.jgdfunction(I)I
        at     TestJNI.jgdfunction(Native Method)
        at     Test.jgdfunction(   Test.java:12)
        at NativeClient.main(NativeClient.java:7)
0
 
LVL 35

Expert Comment

by:mccarl
ID: 39866326
The screenshots show a C method called jgdfunction whereas the stack trace indicates it was looking for jgd_function   (note the UNDERSCORE). Could this be the issue?
0
 

Author Comment

by:jgdvishnu
ID: 39866343
When I raised the question In the second posting I thought underscore in "jgd_function" could be an issue. I removed the underscore completely from every function and file the next time.
so that is unfortunately not the issue. So the stack trace remains.
C:\Program Files (x86)\Java\jdk1.6.0_31\bin>java main

Exception in thread "main" java.lang.UnsatisfiedLinkError:      TestJNI.jgdfunction(I)I
        at      TestJNI.jgdfunction(Native Method)
        at      Test.jgdfunction(     Test.java:12)
        at main.main(main.java:5)

Open in new window


Questons -
1) Is it necessary to register the dll by regsvr32 command followed by dll name. I assume not as I am putting the dll from where I am executing the java program i.e. "C:\Program Files (x86)\Java\jdk1.6.0_31\bin"

2) As the dll Library loads fine, What reflection APIs can be used to find out what methods parameter are expected for the native function.

3) attaching the native Wrapper C file that was generated (if that helps)
Test-wrap.c
0
 
LVL 86

Expert Comment

by:jkr
ID: 39866390
The '@8' is caused by a wrong calling convention then - try '__cdecl' to circuvent that, e.g.

extern "C" void __cdecl test();

Open in new window

0
 
LVL 86

Expert Comment

by:jkr
ID: 39866395
Ooops, sorry, maybe a bit more 'portable':


extern "C" void WINAPIl test();
                                            

Open in new window

0
 

Author Comment

by:jgdvishnu
ID: 39866542
I am using swig to compile the interface(".i" file) and c classes(".c" classes) and it does not allow to compile with suggested keywords before function names

 //extern "C" void _cdecl jgdfunction();  //Error: Syntax error in input(1).
 //extern "C" void WINAPIl test(); //Error: Syntax error in input(1).
extern "C" void  jgdfunction(); // compiles without error

Open in new window

0
 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 39866721
the extern "C" only can used when you compile it by c++ compiler. a c compiler doesn't "understand" that. c++ name mangling only happens when using c++ compiler. when using a .c file the defaults of many ide's would make it compile using the ansi c compiler.

nevertheless, the results are equal when using pure c code.

if you want to export c functions from c dll (or c++ dll using extern "c" declaration") you should use the __declspec(dllexport) specifier. you best do it in a header file where all exported functions would be proceeded by the specifier.

// myheader.h

// the DLL_EXPORTS is a macro that was added to the precompiler options of 
// the dll project. you can use any unique name, the 'DLL_EXPORTS' is only a sample
// if doing so, you can use the dll in c or c++ projects as well by simply not use 
// DLL_EXPORTS for those projects. then they would switch to the dllimport, same as 
// it was done in the JNI interface.

#ifdef DLL_EXPORTS  
#define DLL_IMPEXP __declspec(dllexport)
#else
#define  DLL_IMPEXP__declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C"
{
#endif

// declare exported function
int DLL_IMPEXP jgdfunction(int); 

// declare more functions if needed here 

#ifdef __cplusplus 
}
#endif

Open in new window


note, the above header could be used both from c source and from c++ source cause the extern "C" clause was only added for the latter case.

the last thing you have to check is whether the dll project uses a .def file. a .def file is an alternative way to specifiy exported functions and also an alternative way how to get a function pointer to it by number (see the '@8' in your error). if a .def file exists you should remove it from the project and from build process.

Sara
0
 

Author Comment

by:jgdvishnu
ID: 39867237
Thanks Sara,

gcc uses C compiler by default and i use below commands to compile and generate dll so it should be "C" language and dll be c output

C:\Cplusplus\swigwin-2.0.11>gcc -c Test.c Test_wrap.c -I/C:/Installation/Java6/include -I/C:/Installation/Java6/include/win32

C:\Cplusplus\swigwin-2.0.11>gcc -shared Test.o  Test_wrap.o -o Test.dll


2) There is no ".def" files in the path.

3) I created the "Test.h" as you put it up and in the same directory I still get changed function name (as seen through dependency walker).

Java_TestJNI_jgdfunction@8

Now the root cause is how will the compiler know that Test.h is in the path. Do I have to include that in the commands or include that in "Test.c" or "Test.i" file.

The command that i use to generate the wrapper and c classes are:-
C:\Cplusplus\swigwin-2.0.11>swig -java Test.i

Open in new window

Based on SWIG Tutorial
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 32

Expert Comment

by:sarabande
ID: 39867524
I created the "Test.h" as you put it up
you need to compile the test.c with flag -D DLL_EXPORTS  such that the __declspec(dllexports) becomes active. alternatively remove the statements regarding DLL_EXPORTS what doesn't matter as long as you don't want to include the header from a different c/c++ project.

//test.h
#define DLL_EXP __declspec(dllexport)

#ifdef __cplusplus
extern "C"
{
#endif

// declare exported function
int DLL_EXP jgdfunction(int); 

// declare more functions if needed here 

#ifdef __cplusplus 
}
#endif

Open in new window

0
 

Author Comment

by:jgdvishnu
ID: 39868013
Actually I realize that method signature is/may not be the issue as I compared with some well known dlls/APIs of Java and they show the same method signature issue through dependency walker. so it is some other issue.

Nio DLL Showing Void Method  with changed Signature
I am planning to switch the IDE to Free Visual Studio Express Version to make and debug the dll for the native method calls.
0
 

Author Comment

by:jgdvishnu
ID: 39868143
I've requested that this question be closed as follows:

Accepted answer: 0 points for jgdvishnu's comment #a39868013

for the following reason:

this is the only way out
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 39868144
Not ready to be closed yet. What's more people have helped to quite a large extent so to ignore that help by not awarding points shows a lack of gratitude

When you've got a proper solution, come back and tell people what it was and award points
0
 
LVL 86

Expert Comment

by:jkr
ID: 39869297
Agree with the non-closing request. Export by ordinal *is* an issue here.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 39869756
Might also be worth checking for library dependencies
0
 

Accepted Solution

by:
jgdvishnu earned 0 total points
ID: 39870422
Steps to resolve was :-
1) created new "Test.def" file with all the methods listed in format
EXPORTS
Java_CLASSNAME_METHODNAME

Open in new window


command to generate dll contained the def file name also
cl /LD NameofCFile.c NameofCFile.def

Open in new window

(I used cl command provided by windows but this will work with gcc also (using CYGWIN/MingW)

This idea came from this post Steps to remove the Unsatisfied Link Error due to method name issue posted by Carlos Pineda
0
 

Author Comment

by:jgdvishnu
ID: 39876403
I've requested that this question be closed as follows:

Accepted answer: 0 points for jgdvishnu's comment #a39870422
Assisted answer: 250 points for jkr's comment #a39869297

for the following reason:

Thanks to JKR and sarabande
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 39871009
Thanks to JKR and sarabande
So, if you want to thank Sarabande, then why did you not give her (him?) any points..?
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39873240
@CEHJ: thanks, but it is quite ok that my comments did not get an assist if they didn't help to solve the issue.

Sara
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
This video teaches viewers about errors in exception handling.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now