web-dev-qa-db-ja.com

JNIプロジェクトでUnsatisfiedLinkError(依存ライブラリが見つからない)を修正する方法

JNIを使​​用するJavaプロジェクトに取り組んでいます。 JNIは、私が自分で作成したカスタムライブラリ、たとえばmylib.dllを呼び出します。これは、サードパーティライブラリlibsndfile-1.dllに依存しています。

プログラムを実行するとクラッシュします

Java.lang.UnsatisfiedLinkError:  C:\...path...\mylib.dll: Can't find dependent libraries.

このサイト(および他のサイト)を検索し、いくつかの修正を試しました。

  1. 依存関係ウォーカーを実行しました。 DWは、libsndfileに必要な2つのライブラリMPR.DLLとSHLWAPI.DLLに「未解決のインポート」があるという警告をいくつか出しましたが、 DW FAQ はこれらの警告を無視しても安全だと述べました。

  2. here のように、mylib.dllのメソッド名を修正しました。メソッド名はコンパイラによって何らかの形で破壊されましたが、リンカーフラグを追加し、dllメソッド名はjniヘッダーファイルの名前と完全に一致するようになりました。

  3. これらすべてのDLLを同じディレクトリ(それらを呼び出す.jarと同じディレクトリ)に配置して、正しいPATH上にあることを確認します。

サイコロなし。

誰が何が起こっているのか考えていますか?

私はVisual Studio 2010の開発をMacBook Proで(Parallels経由で)行っています。 ToshibaラップトップのWindows XPでテストを行っています。

73
dB'

クラスパスと共有ライブラリの検索パスは互いにほとんど関係がないと確信しています。 The JNI Book (確かに古い)によると、WindowsではJava.library.pathシステムプロパティを使用しない場合、DLLは現在の作業ディレクトリまたはWindows PATH環境変数にリストされているディレクトリ。


更新:

OracleはPDFをWebサイトから削除したようです。上記のリンクを更新して、テキサス大学アーリントン校に住んでいるPDFのインスタンスを指すようにしました。

また、OracleのHTMLバージョンの JNI Specification も読むことができます。それはJavaウェブサイトのJava 8セクションにあるので、しばらくはそうなることを願っています。


更新2:

少なくともJava 8(以前のバージョンはチェックしていません)では、次のことができます。

Java -XshowSettings:properties -version

共有ライブラリの検索パスを見つけます。その出力でJava.library.pathプロパティの値を探します。

43
QuantumMechanic

この興味深いケースをお知らせしたいのですが、上記のすべての方法を試した後、エラーがまだ残っています。奇妙なことに、Windows 7コンピューターでは動作しますが、Windows XPでは動作しません。次に、Dependency Walkerを使用して、Windows XPにdll要件としてVC++ Runtimeがないことを発見しました。 VC++ランタイムパッケージをインストールした後 here それは魅力のように機能します。私が邪魔したのは、依存ライブラリが見つかりません、JNI依存dllがそこにある間、JNI依存dllが別の依存dlを必要とすることが最終的に判明するということです。これがお役に立てば幸いです。

17
longbkit

JNIライブラリをロードする必要があります。

System.loadLibraryJVMパス(JDK binパス)からDLLをロードします。

パスを含む明示的なファイルをロードする場合は、System.load()を使用します

参照: JavaのSystem.load()とSystem.loadLibraryの違い

13
Yochai Timmer

ライブラリパスが正しいかどうかを確認してください。もちろん、次のコードを使用してライブラリパスパスを確認できます:System.out.println(System.getProperty("Java.library.path"));

Javaアプリケーションの起動時にJava.library.pathを指定できます。

Java -Djava.library.path=path ...
5
caopeng

javacvおよびopencvをEclipseと組み合わせてインストールするときに、XPマシンで同じ問題が発生しました。次のファイルが欠落していることがわかりました。

  • msvcp100.dll
  • msvcr100.dll

これらがインストールされると、プロジェクトがコンパイルされ、正常に実行されました。

4
Rob van Riswick

Dllの32ビットバージョンを64ビットJREでロードすると、この問題が発生する可能性があります。これは私の場合でした。

3
EFalco
  • 短い答え:「依存ライブラリが見つかりません」エラーについては、$ PATHを確認してください(下記の箇条書きの3番目に対応)
  • 長い答え:
    1. Pure Java world:jvmは「クラスパス」を使用してクラスファイルを検索します
    2. JNIワールド(Java /ネイティブ境界):jvmは "Java.library.path"(デフォルトは$ PATH)を使用してdllを見つけます
    3. 純粋なネイティブの世界:ネイティブコードは$ PATHを使用して他のdllをロードします
2
user2038596

Keepsafeの友人たちが私と同じことを行ったすばらしい記事を見つけました。それは私のために働いたので、うまくいけばそれもあなたを助けます!興味がある場合( Androidにネイティブライブラリをロードする際の危険 )または単に使用する場合は読んでください

compile 'com.getkeepsafe.relinker:relinker:1.2.3'

そして交換

System.loadLibrary("myLibrary");

ReLinker.loadLibrary(context, "mylibrary");
2
rhysl

私の状況では、Eclipseのコネクターを介してTomcat 7でJava Webサービスを実行しようとしました。私のラップトップ上のTomcat 7のインスタンスにwarファイルをデプロイすると、アプリはうまく動作しました。アプリには、「IBM DB2 9.5」用のjdbcタイプ2ドライバーが必要です。何らかの奇妙な理由で、Eclispeのコネクターは、IBM DB2環境変数内のパスを表示または使用して、jccクライアントとしてラップトップにインストールされたdllファイルに到達できませんでした。エラーメッセージには、db2jcct2 dllファイルが見つからなかったか、そのdllファイルの依存ライブラリが見つからなかったことが記載されています。最終的に、コネクタを削除して再構築しました。その後、正常に機能しました。この特定のソリューションを他の場所で見つけることができなかったため、ここにドキュメントとしてこのソリューションを追加しています。

1
bwfrieds

私は同じ問題を抱えていたので、ここに掲載されているものをすべて修正して修正しましたが、うまくいきませんでした。私の場合、Cygwinを使用してdllをコンパイルしています。 JVMは仮想CygwinパスでJRE DLLを見つけようとしているようです。 Cygwinの仮想ディレクトリパスをJREのDLLに追加しましたが、現在は動作しています。私は次のようなことをしました:

SET PATH = "/ cygdrive/c/Program Files/Java/jdk1.8.0_45";%PATH%

1
estebanuri

以前はまったく同じ問題を抱えていましたが、ようやく解決しました。

すべての依存DLLをmylib.dllが保存されている同じフォルダーに入れ、Javaコンパイラーがそれを検出できることを確認します(コンパイルパスにmylib.dllがない場合、エラー報告がありますコンパイル中)。注意する必要がある重要なことは、すべての依存ライブラリがmylib.dllと同じバージョンであることを確認する必要があることです。たとえば、mylib.dllがリリースバージョンである場合、その依存ライブラリすべてのリリースバージョンもそこに配置する必要があります。 。

これが同じ問題に遭遇した他の人を助けることを願っています。

1
Steven Peng

g++ -staticを使用してコンパイルし、静的ライブラリの作成はうまくいきました。ビルドとともに依存ライブラリをバンドルします。

0
Caesar