JNI: library found on path, but method not (java.lang.UnsatisfiedLinkError)

I am trying to use JNI and getting java.lang.UnsatisfiedLinkError. Unlike the other millions of questions asked about this, I have lib in my path and even saw the exception change when I delete it. I am sure something is wrong with the DLL I created, but I am not sure what.

Here is my java class code:

package com; public class Tune { static { System.loadLibrary("lala"); } public static void main(String[] args) { Tune j = new Tune(); System.out.println("2+6="+j.add(2, 6)); } native public int add(int x,int y); } 

Here is a shortened part of my javah created header file:

 /* * Class: com_Tune * Method: add * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_Tune_add (JNIEnv *, jobject, jint, jint); 

Here is my C ++ code:

 #include <jni.h> #include <com_Tune.h> JNIEXPORT jint JNICALL Java_com_Tune_add (JNIEnv * env, jobject obj, jint x, jint y) { return x+y; } 

Here is the runtime exception that I get from eclipse:

 Exception in thread "main" java.lang.UnsatisfiedLinkError: com.Tune.add(II)I at com.Tune.add(Native Method) at com.Tune.main(Tune.java:9) 

I read that the above exception means that he found the lala library, but the add method is not yet defined. The only thing I see differently between my project and the tutorial is:

  • Mine uses the package instead of the default package (shouldn't it really be?)
    • I have a return value.
    • I moved my dll after it was created (I don't think this will break it since my path is configured.)

How is this possible?

Additional Information:

OS: Windows 7
JDK: 1.6.0_31 (for x86, 32 bit jvm)
C ++ IDE: Code :: Blocks (dll was compiled automatically using Code :: Blocks IDE)
C ++ Compiler: MinGW32-g ++ (GNU C ++ Compiler)

I have jni.h and com_Tune.h in C: \ _ \ include
I have lala.dll in C: \ _ \ lib

Environment Variables:
PATH: C: \ Program Files (x86) \ NVIDIA Corporation \ PhysX \ Common;% CommonProgramFiles% \ Microsoft Shared \ Windows Live; C: \ Program Files (x86) \ AMD APP \ bin \ x86_64; C: \ Program Files (x86) \ AMD APP \ bin \ x86;% SystemRoot% \ system32;% SystemRoot%;% SystemRoot% \ System32 \ Wbem;% SYSTEMROOT% \ System32 \ WindowsPowerShell \ v1.0 \; C: \ Program Files (x86) \ ATI Technologies \ ATI.ACE \ Core-Static; C: \ Apps;% JAVA_HOME% \ bin; C: \ Program Files \ MySQL \ MySQL Server 5.5 \ bin;% MAVEN_HOME% \ bin;% HADOOP_INSTALL% \ bin; c: \ Program Files (x86) \ Microsoft SQL Server \ 100 \ Tools \ Binn \; c: \ Program Files \ Microsoft SQL Server \ 100 \ Tools \ Binn \; c: \ Program Files \ Microsoft SQL Server \ 100 \ DTS \ Binn \; C: \ MinGW \ bin; C: \ Program Files (x86) \ GnuWin32 \ bin; C: _ \ path; C: \ _ \ lib; C: \ Program Files (x86) \ Microsoft Visual Studio 10.0 \ VC \ Bin; C: \ _ \ enable

+6
source share
5 answers

Just guessing ... Is your dll dependent on another dll that is not in the way? MinGW modules typically depend on a specific C runtime library.

+1
source

Problem creating compiler name: Java_com_Tune_add@16

Use either of two

gcc -Wl,-kill-at

Or

gcc -Wl,--add-stdcall-alias

This will ensure the generation of Java_com_Tune_add

And then your method call will succeed.

+4
source

One possible source of the problem may be that you compiled the code using the C ++ compiler, which uses a different [calling convention] than regular C. If so, then the solution would be to wrap the code for the method in extern "C" , for example:

 #ifdef __cplusplus extern "C" { #endif JNIEXPORT jint JNICALL Java_com_Tune_add ... #ifdef __cplusplus } #endif 
+2
source

I had the same problem and the -Wl, -kill-at flag worked for me.

0
source

Try the following example for Windows: (remember that the name of the Java class must match the name of the corresponding file)

Step 1. Create the following Java file (P.java):

 class P { static { // "P" is the name of DLL without ".dll" System.loadLibrary ("P"); } public static native void f(int i); public static void main(String[] args) { f(1); } } 

Step 2.javac P.java

Step 3.javah P

Then "javah" generates the header file "Ph"

Step 4. Create a β€œP.def” file, including the following two lines (this file defines the exported characters, in this case the function name C):

 EXPORTS Java_P_f 

Step 5. Create your C file (Pc):

 #include "Ph" JNIEXPORT void JNICALL Java_P_f(JNIEnv *env, jclass c, jint i) { printf("%i\n",i); } 

Step 6. At the Visual Studio command prompt, define the following variables:

set JAVA_HOME = JDK path

set include =% include%;% JAVA_HOME% \ include;% JAVA_HOME% \ include \ win32

Step 7. Creating the DLL:

cl / LD Pc P.def

Step 8. Run the Java program:

java P

(Note: P.dll and P.class are in the same directory)

0
source

Source: https://habr.com/ru/post/908922/


All Articles