Java JNI Hello World 不满意链接错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1358541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JNI Hello World Unsatisfied Link Error
提问by Ken
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.
这是我第一次尝试 JNI。我的最终目标是让当前在一台机器上运行的所有任务,但甚至需要运行一个简单的示例。当我尝试执行我的主程序时,我不断收到此错误。我提供了我的简单 Java 主程序、生成的头文件和错误。
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).
我不知道这个 DLL 可能依赖什么。它最初引用了我追踪并放入 system32 (msvcr90.dll) 的 DLL。
Here is the command I used to compile the C code as well which produced the DLL, OBJ, LIB, EXP and manifest files.
这是我用来编译 C 代码的命令,它生成了 DLL、OBJ、LIB、EXP 和清单文件。
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
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 <jni.h>
#include <stdio.h>
#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 <jni.h>
/* 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.<clinit>(HelloWorld.java:7)
Exception in thread "main"
回答by Bruno Sim?es
I'm not claiming to understand the situation enough to explain it, however some users reported the error when using the "-MD" compiler flag.
我并没有声称对这种情况的了解足以解释它,但是一些用户在使用“-MD”编译器标志时报告了错误。
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 blogfor alternatives.
有关更多信息,请参阅Java Native Interface (JNI) - Impossible to use VS2005 with Java? 它讨论了这个问题,并提供了可能的解决方法,并考虑了技术博客的替代方案。
回答by TwentyMiles
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.
而不是 System.load。LoadLibrary 将检查您的系统路径(而不是 Java 库路径),因此请确保 HelloWorld.dll 位于它可以找到的目录中。另请注意,它不需要完整路径,也不需要在末尾添加 dll 扩展名。
回答by Cesar
The Unsatisfied Link Error can mean many things went wrong. I would use
Unsatisfied Link Error 可能意味着很多事情都出错了。我会用
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:
此外,在调用您的程序时,您需要(假设您的 DLL 与类文件位于同一目录中:
java -Djava.library.path=. HelloWorld
java -Djava.library.path=. 你好,世界
Here's a simple demo I made that calls a Win32 API function (MessageBox)
这是我制作的一个调用 Win32 API 函数 (MessageBox) 的简单演示
Java class
Java类
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 <jni.h>
/* 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
C DLL 代码
#include "CallApi.h"
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#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:
我使用 Visual C++ express 2008 cl 进行编译,删除了 -ML 标志,因为当 Java 代码尝试调用本机代码时它会导致异常:
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
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
java -Djava.library.path=. 调用接口
回答by sreekanth
I just removed -MD option and compiled it worked like charm
我刚刚删除了 -MD 选项并编译它就像魅力一样
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
回答by Li3ro
If you change the location (package) of your native function declaration from the java side without updating the h file, and the signature of the method in the c++ side, It won't resolve to the method and will throw unsatisfied..
如果在没有更新h文件的情况下从java端改变了本地函数声明的位置(包),以及在c++端的方法签名,它不会解析到该方法并且会抛出unsatisfied..
package x;
public class A {
private native void print();
...
}
moved to:
搬去:
package x.y;
public class A {
private native void print();
...
}
This will require regeneration of the H file (to something like Java_x_y_A_print ).
这将需要重新生成 H 文件(类似于 Java_x_y_A_print )。
Note you can change those signatures manually but I won't recommend
请注意,您可以手动更改这些签名,但我不建议