JNI Hello World Unsatisfied Link Error

匿名 (未验证) 提交于 2019-12-03 02:24:01

问题:

This is my first attempt at JNI. My ultimate goal is to get all tasks currently running on a machine, but need to get even a simple example running. I keep getting this error when I try to execute my main program. I have supplied my simple Java main program, the header file generated, and the error.

I do not know what this DLL could be dependent on. It was initially referencing a DLL I tracked down and placed into system32 (msvcr90.dll).

Here is the command I used to compile the C code as well which produced the DLL, OBJ, LIB, EXP and manifest files.

cl -I"C:\Program Files\Java\jdk1.6.0\include" -I"C:\Program Files\Java\jdk1.6.0\include\win32" -MD -LD HelloWorld.c -FeHelloWorld.dll

class HelloWorld {      private native void print();      public static void main(String[] args) {          new HelloWorld().print();      }      static {          System.load("C:\\temp\\HelloWorld.dll");      }  }   #include   #include   #include "HelloWorld.h"   JNIEXPORT void JNICALL   Java_HelloWorld_print(JNIEnv *env, jobject obj)  {      printf("Hello World!\n");      return;  }  /* DO NOT EDIT THIS FILE - it is machine generated */ #include  /* Header for class HelloWorld */  #ifndef _Included_HelloWorld #define _Included_HelloWorld #ifdef __cplusplus extern "C" { #endif /*  * Class:     HelloWorld  * Method:    print  * Signature: ()V  */ JNIEXPORT void JNICALL Java_HelloWorld_print   (JNIEnv *, jobject);  #ifdef __cplusplus } #endif #endif  java.lang.UnsatisfiedLinkError: C:\temp\HelloWorld.dll: A dynamic link library (DLL) initialization routine failed     at java.lang.ClassLoader$NativeLibrary.load(Native Method)     at java.lang.ClassLoader.loadLibrary0(Unknown Source)     at java.lang.ClassLoader.loadLibrary(Unknown Source)     at java.lang.Runtime.load0(Unknown Source)     at java.lang.System.load(Unknown Source)     at HelloWorld.(HelloWorld.java:7) Exception in thread "main"  

回答1:

The Unsatisfied Link Error can mean many things went wrong. I would use

System.loadLibrary("HelloWorld"); 

Instead of

System.load(); 

As TwentyMiles suggested.

Also, when invoking your program you need to (assuming your DLL is on the same directory as your class files:

java -Djava.library.path=. HelloWorld

Here's a simple demo I made that calls a Win32 API function (MessageBox)

Java class

class CallApi{     private native String showMessageBox(String msg);     private native double getRandomDouble();      static{         try{             System.loadLibrary("CallApi");             System.out.println("Loaded CallApi");         }catch(UnsatisfiedLinkError e){             //nothing to do             System.out.println("Couldn't load CallApi");             System.out.println(e.getMessage());         }     }      public static void main(String args[]){         CallApi api = new CallApi();         double randomNumber = api.getRandomDouble();         String retval = api.showMessageBox("Hello from Java!\n"+             "The native random number: "+randomNumber);             System.out.println("The native string: "+retval);     } } 

Generated header file

/* DO NOT EDIT THIS FILE - it is machine generated */ #include  /* Header for class CallApi */  #ifndef _Included_CallApi #define _Included_CallApi #ifdef __cplusplus extern "C" { #endif /*  * Class:     CallApi  * Method:    showMessageBox  * Signature: (Ljava/lang/String;)Ljava/lang/String;  */ JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox   (JNIEnv *, jobject, jstring);  /*  * Class:     CallApi  * Method:    getRandomDouble  * Signature: ()D  */ JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble   (JNIEnv *, jobject);  #ifdef __cplusplus } #endif #endif 

The C DLL code

#include "CallApi.h" #include  #include  #include   #pragma comment(lib,"user32.lib")  JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox   (JNIEnv *env, jobject thisObject, jstring js) {     //first convert jstring to const char for use in MessageBox     const jbyte* argvv = (*env)->GetStringUTFChars(env, js, NULL);     char* argv =(char *) argvv;      //Call MessageBoxA     MessageBox(NULL, argv, "Called from Java!", MB_ICONEXCLAMATION | MB_OK);     return js; }  JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble   (JNIEnv *env, jobject thisObject) {     double num1;     srand((unsigned)(time(0)));     num1 = ((double)rand()/(double)RAND_MAX);      return num1; } 

Compile instructions

I compile with the Visual C++ express 2008 cl, removing the -ML flag since it causes an exception when the Java code tries to call the native code:

cl /I"c:\Program Files\Java\jdk1.6.0_10\include" /I"c:\Program Files\Java\jdk1.6.0_10\include\win32" -LD CallApi.c -FeCallApi.dll

Then, to run the code:

java -Djava.library.path=. CallApi



回答2:

I'm not claiming to understand the situation enough to explain it, however some users reported the error when using the "-MD" compiler flag.

For more information see Java Native Interface (JNI) - Impossible to use VS2005 with Java? which discusses this problem and offers possible work-arounds and think techie blog for alternatives.



回答3:

I believe that you should be using

System.loadLibrary("HelloWorld"); 

instead of System.load. LoadLibrary will check your system path (not the Java library path) so make sure that HelloWorld.dll is in a directory where it can found. Also note that it does not require the full path, and you don't need to add the dll extension to the end.



回答4:

I just removed -MD option and compiled it worked like charm

cl -I"C:\Program Files\Java\jdk1.6.0_21\include" -I"C:\Program Files\Java\jdk1.6.0_21\include\win32" -LD HelloWorld.c -FeHelloWorld.dll 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!