我试图用C ++从Java中调用一个简单的本机方法,为此我做了以下几点:
创建一个简单的类,如下所示:
public class HelloNative{
public native void printString(String str);
static{
System.out.println("Current Directory is: " + System.getProperty("user.dir"));
System.load(System.getProperty("user.dir") + "/libhellonative.so");
}
public static void main(String[] args){
System.out.println("Calling Native Libraray (libhellonative.so) method printString");
new HelloNative().printString("Message from Java to C");
}
}
使用javah -jni
为本机方法创建.h文件,创建以下声明:
JNIEXPORT void JNICALL Java_HelloNative_printString(JNIEnv *, jobject, jstring);
在.cpp
文件中实现原生函数:
JNIEXPORT void JNICALL Java_HelloNative_printString(JNIEnv* jni_env, jobject java_obj, jstring msg){
printf("inside native method\n");
jboolean iscopy;
const char *message = (jni_env)->GetStringUTFChars( msg, &iscopy);
printf("%s", message);
}
最后使用:
创建.so
文件
g++ HelloNative.cpp -o libhellonative.so -shared -Wl,-soname,libhellonative.so -static -lc -I /usr/lib/jvm/java-6-sun-1.6.0.26/include -I /usr/lib/jvm/java-6-sun-1.6.0.26/include/linux
但是当我编译并运行.java文件时,它给了我Runtime Exception:
Current Directory is: /home/gmuhammad/Projects/test
Calling Native Libraray (libhellonative.so) method printString
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.printString(Ljava/lang/String;)V
at HelloNative.printString(Native Method)
at HelloNative.main(HelloNative.java:16)
答案 0 :(得分:3)
好的,我让这个工作了。它与加载库无关,而是实际调用该库中的方法。
我通过您的问题复制/粘贴创建了.java
,.h
和.cpp
个文件并运行它们(我必须在#include <jni.h>
中添加.cpp
文件) - 并得到与你完全相同的错误。
然后我编辑了.cpp
文件以包含生成的.h
文件。另外,正如他的回答中指出的 maba ,您需要调用(jni_env)->ReleaseStringUTFChars(msg, message);
来释放该对象。我的完整.cpp
文件现在看起来像这样:
#include "HelloNative.h"
JNIEXPORT void JNICALL Java_HelloNative_printString(JNIEnv* jni_env, jobject java_obj, jstring msg){
printf("inside native method\n");
jboolean iscopy;
const char *message = (jni_env)->GetStringUTFChars( msg, &iscopy);
printf("%s", message);
(jni_env)->ReleaseStringUTFChars(msg, message);
}
我重新编译了库,运行了java代码 - 瞧!一切正常。这样,无论您使用load
还是loadLibrary
加载库的方式,它都能正常工作。
试一试。
答案 1 :(得分:1)
我建议稍微加载库。
将libmynative.so
放入您喜欢的目录。
将该目录添加到LD_LIBRARY_PATH
变量。
在您的java代码中,将System.load
调用更改为System.loadLibrary("mynative")
(请注意缺少完整路径,前缀 lib 和扩展名 .so < / EM>)
运行您的java代码。
请点击此处了解更多详情:http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html
答案 2 :(得分:1)
使用System.load()
是完全可以的,但您必须确保您的共享库确实在您应该的位置。
Current Directory is: /home/gmuhammad/Projects/test
您的代码正在尝试访问该目录中的共享库。你确定libhellonative.so
在那里吗?
然后,您还可以使用System.mapLibraryName("hellonative")
获取当前平台的共享库的名称。这使得它更加独立于平台。该调用将在linux上为您提供libhellonative.so
,在Windows上提供hellonative.dll
。
此外,您必须致电(jni_env)->GetReleaseUTFChars(msg, message);
以释放对象。