Как я должен загрузить собственные библиотеки для JNI, чтобы избежать UnsatisfiedLinkError? - PullRequest
15 голосов
/ 24 мая 2009

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

Тогда это работает, но я бы предпочел не использовать явный путь, если это возможно.

Ответы [ 5 ]

23 голосов
/ 24 мая 2009

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

System.loadLibrary("hello");

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

14 голосов
/ 24 мая 2009

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

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

6 голосов
/ 26 июля 2010

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

  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.so или mv hello.so libhello.so

  3. запустить как: java -Djava.library.path=/home/gavin/Work/workspace/JNI/ Hello

5 голосов
/ 24 мая 2009

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

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

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

3 голосов
/ 16 июня 2017

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

3.1.1. Shared Library Names

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...