2009-05-24 8 views
12

Voglio usare JNI su Ubuntu 8.10, usando Eclipse e gcc (quello standard con Ubuntu se ci sono aromi).Come caricare le librerie native per JNI per evitare un UnsatisfiedLinkError?

Non riesco a caricare la mia libreria nonostante il file make lo abbia creato correttamente.

La classe Java principale è la seguente:

class Hello { 
    public native void sayHello(); 

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

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

mio make file è in quanto tale;

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 

Il resto del codice (ciao.c) si presenta come si potrebbe pensare.

L'errore che sto ottenendo è il seguente;

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

Se uso un percorso esplicito:

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

allora funziona, ma mi piacerebbe molto meglio non utilizzare un percorso esplicito, se possibile.

+0

Grazie mille per l'aiuto, i tuoi suggerimenti sono stati tutti corretti, la mia mancanza di la reputazione mi impedisce di notarli tutti come utili. Cheers – gav

+0

si prega di seguire questo link per maggiori dettagli http://saurabhsharma123k.blogspot.in/2017/07/java-jni-and-cc-from-command-line.html –

risposta

21

Come per Pax, è necessario impostare il percorso della libreria sul punto in cui Java deve cercare la libreria. Il nome della tua libreria dovrebbe essere libhello.so. La chiamata di caricare la libreria dovrebbe quindi essere:

System.loadLibrary("hello"); 

librerie Linux si fa riferimento nella convenzione lib nome .so e caricati in base al nome. Ecco uno link sui problemi di collegamento dinamico in Java dalla documentazione SWIG, sebbene non si stia utilizzando SWIG questa sezione è ancora rilevante.

+0

Il collegamento è a posto, ma la nota sull'uso di "-rpath" è falsa. Per 'rpath to work, dovrebbe essere specificato durante la compilazione di quella macchina virtuale java stessa. –

5

E sono in esecuzione con qualcosa di simile:

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

Avrai bisogno di assicurarsi che l'oggetto condiviso è in percorso di libreria.

+0

E se la libreria nativa è accessibile tramite JNA (non JNI), devi invece definire jna.library.path. –

12

Stai chiamando System.loadLibrary() errato. Il metodo loadLibrary accetta un nome di libreria, ad es. "ciao", e prova a caricare l'oggetto condiviso corrispondente. Su Unix, tenterà di caricare "libhello.so", e su Windows tenterà di caricare "hello.dll". Si prevede che il file sia trovato in java.library.path.

Il metodo che si intende chiamare è System.load() che accetta un nome file completo e lo carica. Questo metodo dovrebbe richiedere un argomento come File, ma accetta una stringa. Se si utilizza load, sarà necessario gestire le convenzioni di denominazione locale manualmente, ma non sarà necessario fare affidamento su java.library.path da impostare.

6

procedere come segue:

  1. cambiamento la classe Java a questo:

    class Hello { 
    
        public native void sayHello(); 
    
        static { 
         System.loadLibrary("hello"); 
        } 
    
        public static void main(String[] args) { 
         Hello h = new Hello(); 
         h.sayHello(); 
        } 
    } 
    
  2. rinominare hello.so a libhello.così: cp hello.so libhello.so o mv hello.so libhello.so

  3. Esegui come: java -Djava.library.path=/home/gavin/Work/workspace/JNI/ Hello

3

OS: 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(); 
       } 
} 

esportazione java casa: export JAVA_HOME =/usr/java/jdk1.7.0_67-Cloudera/

classe di compilazione java:

javac JNIHello.java 

generare JNIHello. h:

javah JNIHello 

implementare sayHello in 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; 
} 

biblioteca di compilazione:

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

run JNIHello:

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

lib formato ref name:

3.1.1. Shared Library Names 

Ogni libreria condivisa ha chiamato un nome speciale del `` soname ''. Il soname ha le prefisso 'lib', il nome della libreria, il frase '.so',

ref link

Problemi correlati