4

Linuxで実行しようとしているJNIを介してCコードを呼び出すJavaプログラムがあります。外部コードは、2つの.soファイルで構成されています。1つはJNIバインディング(swigで構築)用で、もう1つは実際の関数用です。同じディレクトリに2つのライブラリがあり、LD_LIBRARY_PATHが正しく設定されています。lddはコマンドラインから実行しても問題を報告しませんが、Eclipseエディターの[構成の実行]ダイアログでLD_LIBRARY_PATHを同じ値に設定してプログラムを実行しようとすると、次のエラーが発生します。

java.lang.UnsatisfiedLinkError:[ライブラリへのパス] /[JNIバインディングライブラリ].so:[実際のコードライブラリ] .so:共有オブジェクトファイルを開くことができません:そのようなファイルまたはディレクトリはありません

これにより、JNIラッパーライブラリが正常にロードされたと思いますが、そのライブラリが実際のコードを含むライブラリをロードしようとすると失敗します。これをさらにデバッグする方法はありますか?

さらに、この問題はeclipseエディター自体で発生しており、コードをjarにパッケージ化して、独立したjvmインスタンス内で実行しようとしたことはありません。

4

7 に答える 7

2

System.loadLibrary(String) の呼び出しと LD_LIBRARY_PATH の使用に問題があると思います。loadLibrary("foo") を使用すると、java.library.path で libfoo.so という名前のものが検索されます。libfoo.so という名前のものが見つからない場合、このエラーが発生します。

LD_LIBRARY_PATH を設定するだけで、必要なネイティブ シンボルがリンカーによって自動的に取得されるため、-Djava.library.path を設定する必要はありません。

gdal プロジェクトで swig を使用した私の経験では、このエラーは実際には無害であり、LD_LIBRARY_PATH が設定されているため、これは正常に機能します。

-Djava.library.path を使用して loadLibrary を明示的に呼び出すことをお勧めします。その理由は、webstart を使用してアプリをデプロイすることにした場合、明示的に loadLibrary を呼び出してネイティブ ライブラリを取得する必要があるからです。

Eclipse を使用するときは、ビルド パスの [ライブラリ] タブで jar の下にあるネイティブ ライブラリを編集する場所で Daff が提供した指示に従います。もう一度言いますが、これは java.library.path を設定するだけです。

于 2009-06-24T06:26:22.917 に答える
1

-Djava.library.path=... オプションを配置するには、実行構成ダイアログで適切な場所を見つける必要があるだけかもしれません。環境タブにあるLD_LIBRARY_PATHを定義したい場合は、引数タブの「vm引数」で-D定義が必要だと思います。Eclipse は、あなたが意味すると思っていることを意味しない場所に物を置くことを喜んで許してくれます。とにかく、以前にこの方法でライブラリを使用したことがあります。機会があれば、自分が行ったことを調べて、ここで回答を編集します。

もう 1 つの試みは、LD_DEBUG で遊ぶことです。環境変数 LD_DEBUG をさまざまなものに設定できます (ALL を試してください)。すると、Linux ローダーは、アプリケーションが何をロードしようとしているのか、どこで何かを探しているのかなど、あらゆる種類の有用な情報を漏らします。コマンドラインからEclipseを起動すると仮定しているため、環境変数を設定し、ローダーの診断を確認できます。ただし、システムに関する限り、Eclipse 内からアプリを実行する場合、アプリは Eclipse が実行しているものにすぎないため、ライブラリの読み込み動作はこの方法で確認できます。

于 2009-06-24T23:39:52.243 に答える
0

この回答を追加すると役立つ場合があります。AIXマシンでは、LD_LIBRARY_PATHの代わりにLIBPATH環境変数を設定する必要があります。

于 2012-11-20T06:59:18.490 に答える
0

私の知る限り、Eclipse は LD_LIBRARY_PATH を使用しません。適切なネイティブ ライブラリ パスを設定する最も簡単な方法は、[プロジェクト プロパティ] -> [Java ビルド パス] -> [ライブラリ] に移動することです。次に、JRE システム ライブラリ エントリまたは (利用可能な場合) ネイティブ ライブラリを使用する Jar ファイルを展開し、[ネイティブ ライブラリ] を選択します。ライブラリの場所」をクリックし、「編集...」をクリックして、ライブラリがあるフォルダーを選択します。実際には -Djava.library.path 変数が設定されるため、Eclipse の外部からプログラムを起動する場合は、コマンドラインにこれ​​を含める必要があります。 .

于 2009-06-18T12:33:36.997 に答える
0

2 つのライブラリが依存している他のライブラリはありますか? その場合、それらが JVM からもアクセス可能であることを確認する必要があります。

「-Djava.library.path」を手動で設定すると、デフォルトのライブラリパスが消去されるように見えることに注意してください。

したがって、次のコードを使用します。

public class LibTest {
    public static void main(String[] args) {
        String property = System.getProperty("java.library.path");
        StringTokenizer parser = new StringTokenizer(property, ":");
        while (parser.hasMoreTokens()) {
            System.err.println(parser.nextToken());
        }
    }
}

Java 1.6.0_14 出力で Eclipse から起動:

/opt/java/jre/lib/i386/client
/opt/java/jre/lib/i386
/opt/java/jre/../lib/i386
/opt/java/jre/lib/i386/client
/opt/java/jre/lib/i386
/usr/lib/xulrunner-devel-1.9.0.11
/usr/lib/xulrunner-devel-1.9.0.11
/usr/java/packages/lib/i386
/lib
/usr/lib

しかし、JVM 引数 "-Djava.library.path=/tmp/" を設定すると、次のようになります。

/tmp/

手動で java.library.path を設定している場合、コマンド ラインからは ldd が機能するのに、.so は eclipse/java からは機能しない理由が説明される場合があります。

System.loadLibrary を呼び出す代わりに、java.library.path を設定せずに、ライブラリへの絶対パスを指定して System.load を使用することができます。これにより、JVM が .so を見つけ、その依存関係を検索するときにデフォルト パスを引き続き使用できる場合があります。

もちろん、これが役に立たない場合は、コマンド ラインで「-verbose:jni」を使用して jni デバッグ出力を有効にすることもできます。これにより、問題の手がかりが得られる場合があります。

于 2009-06-29T21:21:04.900 に答える
0

はい、LD_LIBRARY_PATHは私のために働いた

于 2010-11-10T06:28:32.360 に答える