8

JNI経由でcpp共有ライブラリlibclient.soを使用するJavaプログラムClient.classがあります。libclient.so は共有としてビルドされ、cpp 共有ライブラリ libhttp.so を使用します。

libclient.so と libhttp.so は、Client.class が配置されているフォルダーに配置されます/home/client/lib64
/home/client/bin

クライアントはライブラリをロードできます

  1. System.load と環境変数 LD_LIBRARY_PATH
  2. System.loadLibrary および -Djava.library.path

最初の方法はうまくいきます。

export LD_LIBRARY_PATH = /home/client/lib64

java -classpath ./bin クライアント

2 番目の方法は失敗します。

java -classpath ./bin -Djava.library.path=./../lib64 Client

java.lang.UnsatisfiedLinkError: /home/client/lib64/libclient.so: libhttp.so: cannot open shared object file: No such file or directory

libhttp.so を /usr/lib64 に入れると、2 番目の方法で問題なく動作します。

System.loadLibrary を使用している場合、libclient.so が /usr/lib64 で libhttp.so を探しているのはなぜですか? libhttp.so を /usr/lib64 にコピーせずに修正するにはどうすればよいですか?

私の読み込みコード:

    //Try load from -Djava.library.path        
    boolean found = false;
    String lib = "client";
    try {
       System.loadLibrary(lib);
       found = true;
    } catch (UnsatisfiedLinkError e) {
       e.printStackTrace();
    }
    //Try load from LD_LIBRARY_PATH
    if (!found) {
       lib = "libclient.so";
       String ld_lib_path = System.getenv("LD_LIBRARY_PATH");
       String[] paths = ld_lib_path.split(":");
       for(int i=0; i<paths.length; i++) {
          String p = paths[i];
          File x = new File(p, lib);
          if (x.exists()) {
             System.load(x.getAbsolutePath());
             found = true;
             break;
          }
       }
    }

追加情報。

ldd で libclient.so をテストすると、次のように表示されます: libhttp.so => 見つかりません export LD_LIBRARY_PATH = /home/client/lib64 を設定すると、次のように表示されます:

4

3 に答える 3

10

これは、libclient.so が JVM からロードされ、java.library.path. ただし、libclient.so が libhttp.so をロードしようとすると、Java については何も認識せず、通常の Linux の共有ライブラリ (ダイナミック リンカーld.so)をロードする方法のみを使用しLD_LIBRARY_PATHます/usr/lib64

LD_LIBRARY_PATHおそらく、Java アプリケーションの開始スクリプトから setを使用することになるでしょう。開始スクリプトを使用したくない場合は、理論的LD_LIBRARY_PATHにはプロセス自体から設定できます。ただし、Java はこれを行うことを許可していません ( のみSystem.getenv()で、 はありません)。そのため、Java から呼び出され、 settingSystem.setenv()を呼び出す小さな C ライブラリを作成する必要があります。putenv()LD_LIBRARY_PATH

自分自身をビルドする場合libclient.soは、リンカー フラグを使用して-rpath、ダイナミック リンカーがさらに必要なライブラリを探すパスを指定できます。ここで相対パスを指定する場合は注意してください。相対パスは、実行中のアプリケーションの現在の作業ディレクトリに対する相対パスとして解釈されますlibclient.so。これを実現するには、$ORIGINas 引数を使用する必要があり-rpath、シェルがこれを展開しないように注意してください。

したがって、同じディレクトリにlibclient.soとを置きたい場合libhttp.soは、使用する必要があります

-rpath '$ORIGIN'

ビルド時のリンカーへの引数としてlibclient.so。リンカーを直接呼び出さずに、コンパイラに呼び出させる場合は、コンパイラのコマンド ラインに次を追加する必要があります。

-Wl,-rpath,'$ORIGIN'

詳細については、 のマニュアル ページを参照してくださいld.so

于 2013-04-26T10:33:20.670 に答える
2

この質問に対する良い答えはありません。

しかし、私はいくつかの良い方法を見つけました。

  1. libhttp.so をライブラリの共有場所 (/usr/lib64 など) に配置します。
  2. libhttp.so へのパスを LD_LIBRARY_PATH に入れます。
  3. 内部に libhttp.so を含む libclient.so をビルドします。
  4. libclient.so のビルド中に -rpath を使用します。
于 2013-04-26T07:24:51.220 に答える
0

異なる OS のライブラリを ( java.library.pathから) 正しく検索するには、異なる名前が必要です。

  • Linux: libhttp.so
  • Windows: http.dll

Javaから呼び出すことができるよりも:

System.loadLibrary( "http" );
于 2016-06-14T16:38:54.237 に答える