17

我想在 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");

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

4

5 回答 5

23

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

System.loadLibrary("hello");

Linux 库由约定的 lib名称.so 引用,并根据名称加载。这是 SWIG 文档中有关 Java 中动态链接问题的链接,尽管您没有使用 SWIG,但此部分仍然相关。

于 2009-05-24T15:21:18.310 回答
17

你打电话System.loadLibrary()不正确。该loadLibrary方法采用库名称,例如“hello”,并尝试加载相应的共享对象。在 Unix 上,它将尝试加载“libhello.so”,而在 Windows 上,它将尝试加载“hello.dll”。它将期望文件可以在java.library.path.

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

于 2009-05-24T11:19:59.827 回答
6

请执行下列操作:

  1. 将您的 Java 类更改为:

    class Hello {
    
        public native void sayHello();
    
        static {
            System.loadLibrary("hello");
        }
    
        public static void main(String[] args) {
            Hello h = new Hello();
            h.sayHello();
        }
    }
    
  2. 将 hello.so 重命名为 libhello.so: cp hello.so libhello.somv hello.so libhello.so

  3. 运行为:java -Djava.library.path=/home/gavin/Work/workspace/JNI/ Hello

于 2010-07-26T16:53:33.717 回答
5

您是否使用以下方式运行它:

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

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

于 2009-05-24T11:05:25.393 回答
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 主页:导出 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!

库名称格式参考:

3.1.1. Shared Library Names

每个共享库都有一个特殊的名称,称为“soname”。soname 有前缀 'lib',库的名称,短语 '.so'

参考链接

于 2017-06-16T08:20:19.167 回答