可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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