2009-05-24 15 views
12

私はUbuntu 8.10でEclipseとgcc(味がある場合はUbuntuの標準のもの)を使用してJNIを使​​いたいと思います。UnsatisfiedLinkErrorを避けるためにJNI用のネイティブライブラリをロードするにはどうすればよいですか?

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

私のメイクファイルは、次のようなです。

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"); 

が、それは動作しますが、可能であれば、私はむしろ明示的なパスを使用しないと思いますが。

+0

おかげで、あなたのヒントは、すべての私の不足正しかったです評判は、私がそれらをすべて参考にすることから除外します。 乾杯してください – gav

+0

詳細については、このリンクをご覧くださいhttp://saurabhsharma123k.blogspot.in/2017/07/java-jni-and-cc-from-command-line.html –

答えて

21

Paxごとに、ライブラリパスをJavaがライブラリを探す場所に設定する必要があります。ライブラリ名はlibhello.soでなければなりません。ライブラリをロードするための呼び出しは、次のようになります。

System.loadLibrary("hello"); 

のLinuxライブラリは、の.so libの慣例によって参照され、名前に基づいてロードされます。 SWIGを使用していないにもかかわらず、SWIGのマニュアルからJavaの動的リンクの問題についてはlinkですが、このセクションはまだ関連しています。

+0

リンクは問題ありませんが、 '-rpath'の使用に関する注意は偽です。 'rpathを動作させるには、その仮想マシン自体をコンパイルするときにrpathを指定する必要があります。 –

5

そして、あなたのようなもので、それを実行している:あなたは共有オブジェクトがであなたのライブラリーのパスであることを確認する必要があります

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

+0

また、ネイティブライブラリにJNA経由でアクセスする場合は(JNIではなく)、jna.library.pathを定義する必要があります。 –

12

あなたはSystem.loadLibrary()を間違って呼び出しています。 loadLibraryメソッドは、ライブラリ名をとります。 "hello"を呼び出し、対応する共有オブジェクトをロードしようとします。 Unixでは、 "libhello.so"をロードしようとし、Windowsでは "hello.dll"をロードしようとします。ファイルがjava.library.pathにあることが予想されます。

呼び出す予定の方法は、完全修飾ファイル名を使用して読み込むSystem.load()です。このメソッドは引数としてFileを取りますが、代わりに文字列を取ります。 loadを使用する場合は、ローカルの命名規則を手動で処理する必要がありますが、java.library.pathを設定する必要はありません。

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. はlibhelloするhello.soの名前を変更します。そう:java -Djava.library.path=/home/gavin/Work/workspace/JNI/ Hello

3

OS:CentOS6.5など cp hello.so libhello.soまたはmv hello.so libhello.so

  • 実行。 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 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; 
    } 
    

    コンパイルライブラリ:

    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」を持っている、非常に多くの助けのための

    ref link

  • 関連する問題