我应该如何为JNI加载本机库以避免出现UnsatisfiedLinkError?

时间:2009-05-24 10:58:02

标签: java c java-native-interface

我想在Ubuntu 8.10上使用JNI,使用Eclipse和gcc(如果有风味,则使用Ubuntu的标准版本)。

尽管make文件成功创建,我似乎无法加载我的库。

主要的Java类如下:

class Hello {
    public native void sayHello();

    static {
        System.loadLibrary("hello.so");
    }

    public static void main(String[] args) {
        Hello h = new Hello();
        h.sayHello();
    }
}

我的make文件是这样的;

    all : hello.so

hello.so : Hello.o
    gcc -shared -o hello.so Hello.o

Hello.o : Hello.c Hello.h
    gcc -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux -c Hello.c -o Hello.o

Hello.h : Hello.class
    javah -jni Hello

clean :
    -del Hello.h
    -del Hello.o

代码的其余部分(Hello.c)看起来像人们想的那样。

我得到的错误如下;

Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello.so in java.library.path

如果我使用显式路径:

System.loadLibrary("/home/gavin/Work/workspace/JNI/hello.so");

然后它可以工作,但如果可能的话,我宁愿不使用显式路径。

5 个答案:

答案 0 :(得分:23)

根据Pax,您应该将库路径设置为Java应该查找库的位置。您的库名应该是libhello.so。然后,加载库的调用应为:

System.loadLibrary("hello");

Linux库由惯例lib name .so引用,并根据名称加载。以下是关于Java中来自SWIG文档的动态链接问题的link,尽管您没有使用SWIG,但此部分仍然具有相关性。

答案 1 :(得分:13)

您呼叫System.loadLibrary()不正确。 loadLibrary方法采用库名称,例如“hello”,并尝试加载相应的共享对象。在Unix上,它将尝试加载“libhello.so”,在Windows上它将尝试加载“hello.dll”。它会期望在java.library.path

中找到该文件

您可能打算调用的方法是System.load(),它采用完全限定的文件名并加载它。此方法应该以{{1​​}}作为参数,但它需要一个字符串。如果您使用File,则必须手动处理本地命名约定,但您不必依赖load进行设置。

答案 2 :(得分:6)

答案 3 :(得分:5)

你用以下的东西运行它吗?

java -Djava.library.path=/home/gavin/Work/workspace/JNI Hello

您需要确保共享对象位于库路径中

答案 4 :(得分:3)

操作系统:CentOS6.5。 JNIHello.java:

public class JNIHello {
                static {
                                System.loadLibrary("JNIHello");
                }
                private native void sayHello();
                public static void main(String args[]) {
                                JNIHello jniHello = new JNIHello();
                                jniHello.sayHello();
                }
}

导出java home:     export JAVA_HOME = / usr / java / jdk1.7.0_67-cloudera /

编译java类:

javac JNIHello.java

生成JNIHello.h:

javah JNIHello

在JNIHello.c中实现sayHello:

#include <jni.h>
#include <stdio.h>
#include "JNIHello.h"
/*
 * Class:     JNIHello
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_JNIHello_sayHello
  (JNIEnv *env, jobject obj) {
        printf("Hello world!\n");
        return;
}

编译库:

gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" JNIHello.c -fPIC -shared -o JNIHello.so

运行JNIHello:

java -Djava.library.path=/home/ldp/caffe/test/ JNIHello
Hello world!

lib名称格式参考:

3.1.1. Shared Library Names

每个共享库都有一个名为``soname&#39;&#39;的特殊名称。 soname有前缀&#39; lib&#39; ,图书馆名称,词组&#39; .so&#39;

ref link