1

我正在尝试从 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. 为本地方法创建 .h 文件,使用javah -jni该文件创建以下声明:

    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

但是当我编译并运行 .java 文件时,它给了我运行时异常:

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)
4

3 回答 3

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 代码——瞧!一切正常。这样,无论您使用哪种方式加载库,它都可以使用loadloadLibrary

试试看。

于 2012-08-21T16:14:42.630 回答
1

我建议以稍微不同的方式加载库。

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

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

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

  4. 运行你的java代码。

在这里查看更多详细信息:http: //java.sun.com/developer/onlineTraining/Programming/JDCBook/jniexamp.html

于 2012-08-21T13:48:22.007 回答
1

使用它是完全可以的,System.load()但您必须确保您的共享库确实在您所说的位置。

Current Directory is: /home/gmuhammad/Projects/test

您的代码正在尝试访问该目录中的共享库。你确定libhellonative.so那里有吗?

然后你也可以使用System.mapLibraryName("hellonative")获取当前平台的共享库的名称。这使得它更加独立于平台。该电话将libhellonative.so在 Linux 和hellonative.dllWindows 上为您提供。

此外,您必须调用(jni_env)->GetReleaseUTFChars(msg, message);释放对象。

于 2012-08-21T14:38:32.587 回答