Java:调用本机方法,给出“线程中的异常”主“java.lang.UnsatisfiedLinkError”

时间:2012-08-21 13:31:24

标签: java c++ c java-native-interface

我试图用C ++从Java中调用一个简单的本机方法,为此我做了以下几点:

  1. 创建一个简单的类,如下所示:

    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");
         }
    }
    
  2. 使用javah -jni为本机方法创建.h文件,创建以下声明:

    JNIEXPORT void JNICALL Java_HelloNative_printString(JNIEnv *, jobject, jstring);

  3. .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);
    }
    
  4. 最后使用:

    创建.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

  5. 但是当我编译并运行.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)
    

3 个答案:

答案 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)

我建议稍微加载库。

  1. libmynative.so放入您喜欢的目录。

  2. 将该目录添加到LD_LIBRARY_PATH变量。

  3. 在您的java代码中,将System.load调用更改为System.loadLibrary("mynative")(请注意缺少完整路径,前缀 lib 和扩展名 .so < / EM>)

  4. 运行您的java代码。

  5. 请点击此处了解更多详情: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);以释放对象。