Подтвердить что ты не робот

Как загружать собственные библиотеки для JNI, чтобы избежать UnsatisfiedLinkError?

Я хочу использовать JNI на Ubuntu 8.10, используя 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");

Затем он работает, но я бы скорее не использовал явный путь, если это было возможно.

4b9b3361

Ответ 1

В соответствии с Pax вы должны установить путь библиотеки туда, где Java должна искать библиотеку. Имя вашей библиотеки должно быть libhello.so. Затем вызов для загрузки библиотеки должен быть:

System.loadLibrary("hello");

Библиотеки Linux ссылаются на соглашение lib name.so и загружаются на основе имени. Ниже приведено link о проблемах динамической компоновки в Java из документации SWIG, хотя вы не используете SWIG, этот раздел по-прежнему имеет значение.

Ответ 2

Вы вызываете System.loadLibrary() неверно. Метод loadLibrary принимает имя библиотеки, например. "привет" и пытается загрузить соответствующий общий объект. В Unix он попытается загрузить "libhello.so", а в окнах попытается загрузить "hello.dll". Он ожидает, что файл будет найден в java.library.path.

Метод, который вы, вероятно, собираетесь вызывать, System.load(), который принимает полное имя файла и загружает его. Этот метод должен принимать аргумент File в качестве аргумента, но вместо этого он берет строку. Если вы используете load, вам придется обрабатывать локальные соглашения об именах вручную, но вам не придется полагаться на java.library.path, который будет установлен.

Ответ 3

Выполните следующие действия:

  • измените свой класс Java на это:

    class Hello {
    
        public native void sayHello();
    
        static {
            System.loadLibrary("hello");
        }
    
        public static void main(String[] args) {
            Hello h = new Hello();
            h.sayHello();
        }
    }
    
  • переименуйте hello.so в libhello.so:   cp hello.so libhello.so или mv hello.so libhello.so

  • выполните как: java -Djava.library.path=/home/gavin/Work/workspace/JNI/ Hello

Ответ 4

И вы запускаете его с чем-то вроде:

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

Вам нужно убедиться, что общий объект находится в вашем пути к библиотеке.

Ответ 5

ОС: 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

реализовать sayHello в JNIHello.c:

#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 ref:

3.1.1. Shared Library Names

Каждая общая библиотека имеет специальное имя, называемое `` soname ''. У soname есть префикс 'lib', имя библиотеки, фраза .so ',

ссылка ссылки