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


85

私は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. ここで提案されているように、mylib.dllのメソッド名を修正しました。メソッド名はコンパイラによってどういうわけか壊れていましたが、リンカフラグを追加し、dllメソッド名がjniヘッダーファイルのメソッド名と正確に一致するようになりました。

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

サイコロはありません。

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

MacBookProのVisualStudio 2010で(Parallels経由で)開発を行っています。私は東芝のラップトップ上のWindowsXPでテストを行っています。


1
-Djava.library.pathを設定しましたか?
Jochen Bedersdorfer 2011年

実際には、コマンドラインからプログラムを起動していないため、起動していません。私はProcessing用のライブラリ(processing.org)を作成しており、Processingはコードの起動を担当しています。ただし、実行時にJavaライブラリパスを確認しましたが、DLLを含むフォルダがその上にあります。
dB '

私が言ったように、すべてのDLLは、私の.jarファイルの隣の同じフォルダーにあります。ですから、問題は彼らが道を進んでいないということではないと思います。どっちにしても、ありがとうね。
dB '

7
Windowsでは、コマンドラインオプションや環境変数をいじくり回すことなくJavaに自動的に表示させるために、[JRE] \ binディレクトリ(java.exeなどと同じ場所)に.dllファイルを配置する必要がありました。
QuantumMechanic 2011年

4
うーん...わかりました。すべての.dllを[JRE] \ binに入れてみました。これはうまくいきます!
dB '

回答:


52

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


更新:

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

また、OracleのHTMLバージョンのJNI仕様を読むこともできます。それはJavaWebサイトのJava8セクションにあるので、しばらくの間は存在することを願っています。


アップデート2:

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

java -XshowSettings:properties -version

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


2
ええ、CLASSPATHまったく使われていません。cwd使用されているかどうかもわかりません。java.library.pathまたは単にPATH動作します。@dB '、あなたが今それらを持っている場所は間違っています。
アーネストフリードマン-ヒル

どうもありがとう!ここでの問題の一部は、WindowsPATH環境変数java.library.pathとjavaCLASSPATHの間の混乱であったと思います。今ではすべてがより理にかなっています。
dB '

この問題をどのように克服したか説明していただけますか?
SL_User 2012年

5
@SL_Userライブラリがあるディレクトリを環境変数「path」に追加し、コマンドプロンプトまたはターミナルを再起動すると、修正されるはずです。Javaは、クラスパスの下でjarを検索し、パスの下でライブラリを検索します。
xxjjnn 2013

1
この回答に基づくと、アップデート2のコマンドは、少なくともJava 7以降で利用可能になっているようです:stackoverflow.com/a/8472139/901641
ArtOfWarfare 2016

18

この興味深いケースをお知らせしたいと思います。上記の方法をすべて試しても、エラーはまだ残っています。奇妙なことに、Windows 7コンピューターでは機能しますが、WindowsXPでは機能しません。次に、依存関係ウォーカーを使用しますが、Windows XPでは、dll要件としてVC ++ランタイムがありません。ここにVC ++ランタイムパッケージをインストールした後、それは魅力のように機能します。私を悩ませたのは、直観的にJNI依存dllが存在するのに、依存ライブラリが見つからないと言い続けることですが、最終的にJNI依存dllには別の依存dlが必要であることがわかりました。これがお役に立てば幸いです。


4
この場合、誤解を招く可能性がありますが、メッセージは正しいです。私は(に応じて、テストボックスとデバッグモードでコンパイルされたライブラリに不足している両方のVC ++ランタイムを持っていた-redistributableデバッグランタイム)。Dependency Walkerは、これを理解するのに大いに役立ちました。
ジョニーバロニー2014

jnetpcap-libraryを使用しても同じ問題が発生しました。依存関係winpcapはマシンにインストールされなくなり、例外メッセージは誤解を招くもの
でした

私はこれが私の場合かもしれないと思っています。
I.Tyger

最近、依存関係ウォーカーはかなり「歯が長く」なっています。最近のWindows10 / 64ビットdllをまったく開くことができなかったので、どのライブラリが欠落しているかはまだわかりません... Whee。
MarkStorer19年


5

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

Javaアプリケーションを起動するときに、java.library.pathを指定できます。

java -Djava.library.path=path ...

4

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


これはおそらく私の場合でもあります。誰かが既知の回避策を知っているなら、私は興味があるでしょう。この場合、プロセスはdllではなくchromedriver.exe、Chrome用のSeleniumドライバーであるため、64ビットバージョンをロードすることを除いて、私が知る限り、32ビットバージョンでのみ提供されます。
SantiBailors 2016

4

インストール時javacvおよびopencvEclipseとの組み合わせ時に、XPマシンで同じ問題が発生しました。次のファイルが欠落していることが判明しました。

  • msvcp100.dll
  • msvcr100.dll

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


「MicrosoftVisualC ++ 2010 SP1再頒布可能パッケージ(x86)」をインストールすると消える同様の問題があります
Kirill Mikhailov

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

2

私がしたのと同じことを経験したkeepsafeの何人かの友人による素晴らしい記事を見つけました。それは私のために働いたので、うまくいけばそれはあなたにも役立つでしょう!興味がある場合は読んでください(Androidでネイティブライブラリをロードすることの危険性)または単に使用する

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

と交換

System.loadLibrary("myLibrary");

ReLinker.loadLibrary(context, "mylibrary");

1

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

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

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


1

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

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


1

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


0

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



0

必要なdllをフォルダーに配置し、PATH環境変数にフォルダーパスを設定します。更新された環境PATH変数が反映されていることを確認してください。


0

2つのAndroidプロジェクトを1つのプロジェクトとしてマージした後、ffmpegライブラリで同じ問題に直面していました。

ffmpegライブラリの2つの異なるバージョンが原因で実際​​に問題が発生していましたが、それらはメモリに同じ名前でロードされました。1つのライブラリはJNiLibsに配置され、もう1つのライブラリはモジュールとして使用される別のライブラリ内に配置されました。モジュールのコードは読み取り専用であるため変更できなかったため、自分のコードで使用されているコードの名前をffmpegCameraに変更し、同じ名前でメモリにロードしました。

System.loadLibrary("ffmpegCamera");

これで問題が解決し、両方のバージョンのライブラリがメモリに別々の名前とプロセスIDをロードしています。


0

を呼び出すSystem.loadLibrary()と、JVMはjava.library.pathネイティブライブラリを探します。ただし、そのネイティブライブラリが他のネイティブライブラリへの依存関係を宣言している場合、オペレーティングシステムはそれらのネイティブライブラリの依存関係を見つける必要があります。

オペレーティングシステムにはの概念java.library.pathがないため、java.library.pathに配置したディレクトリは表示されません。代わりに、オペレーティングシステムのPATH環境変数上のディレクトリのみを検索します。ネイティブライブラリの依存関係がオペレーティングシステムのネイティブライブラリである場合、PATHにあるため、これはまったく問題ありません。ただし、ネイティブライブラリの依存関係が、自分または他の誰かが作成したネイティブライブラリである場合は、PATHに配置しない限り、PATHに依存関係が見つかりません。この動作は奇妙で予期せぬものであり、十分に文書化されていませんが、ここのOpenJDK課題追跡システムに文書化されています。この説明を補強する別のStackOverflowの回答もここにあります

したがって、いくつかのオプションがあります。を使用してSystem.loadLibrary()、各ネイティブライブラリを正しい依存関係の順序でロードするか、PATHを変更して、ネイティブライブラリが格納されているディレクトリを含めることができます。


-2
  1. 移動しhttp://tess4j.sourceforge.net/usage.htmlと上をクリックVisual C++ Redistributable for VS2012
  2. ダウンロードして実行するVSU_4\vcredist_x64.exeVSU_4\vcredist_x84.exe、システム構成によって異なります
  3. 他のライブラリ(例)とともに、dllファイルをlibフォルダ内に配置します\lib\win32-x86\your dll files
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.