JNIを使用するJavaプロジェクトに取り組んでいます。 JNIは、私が自分で作成したカスタムライブラリ、たとえばmylib.dllを呼び出します。これは、サードパーティライブラリlibsndfile-1.dllに依存しています。
プログラムを実行するとクラッシュします
Java.lang.UnsatisfiedLinkError: C:\...path...\mylib.dll: Can't find dependent libraries.
このサイト(および他のサイト)を検索し、いくつかの修正を試しました。
依存関係ウォーカーを実行しました。 DWは、libsndfileに必要な2つのライブラリMPR.DLLとSHLWAPI.DLLに「未解決のインポート」があるという警告をいくつか出しましたが、 DW FAQ はこれらの警告を無視しても安全だと述べました。
here のように、mylib.dllのメソッド名を修正しました。メソッド名はコンパイラによって何らかの形で破壊されましたが、リンカーフラグを追加し、dllメソッド名はjniヘッダーファイルの名前と完全に一致するようになりました。
これらすべてのDLLを同じディレクトリ(それらを呼び出す.jarと同じディレクトリ)に配置して、正しいPATH上にあることを確認します。
サイコロなし。
誰が何が起こっているのか考えていますか?
私はVisual Studio 2010の開発をMacBook Proで(Parallels経由で)行っています。 ToshibaラップトップのWindows XPでテストを行っています。
クラスパスと共有ライブラリの検索パスは互いにほとんど関係がないと確信しています。 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
プロパティの値を探します。
この興味深いケースをお知らせしたいのですが、上記のすべての方法を試した後、エラーがまだ残っています。奇妙なことに、Windows 7コンピューターでは動作しますが、Windows XPでは動作しません。次に、Dependency Walkerを使用して、Windows XPにdll要件としてVC++ Runtimeがないことを発見しました。 VC++ランタイムパッケージをインストールした後 here それは魅力のように機能します。私が邪魔したのは、依存ライブラリが見つかりません、JNI依存dllがそこにある間、JNI依存dllが別の依存dlを必要とすることが最終的に判明するということです。これがお役に立てば幸いです。
JNIライブラリをロードする必要があります。
System.loadLibraryJVMパス(JDK binパス)からDLLをロードします。
パスを含む明示的なファイルをロードする場合は、System.load()を使用します
ライブラリパスが正しいかどうかを確認してください。もちろん、次のコードを使用してライブラリパスパスを確認できます:System.out.println(System.getProperty("Java.library.path"));
Javaアプリケーションの起動時にJava.library.pathを指定できます。
Java -Djava.library.path=path ...
javacv
およびopencv
をEclipseと組み合わせてインストールするときに、XPマシンで同じ問題が発生しました。次のファイルが欠落していることがわかりました。
これらがインストールされると、プロジェクトがコンパイルされ、正常に実行されました。
Dllの32ビットバージョンを64ビットJREでロードすると、この問題が発生する可能性があります。これは私の場合でした。
Keepsafeの友人たちが私と同じことを行ったすばらしい記事を見つけました。それは私のために働いたので、うまくいけばそれもあなたを助けます!興味がある場合( Androidにネイティブライブラリをロードする際の危険 )または単に使用する場合は読んでください
compile 'com.getkeepsafe.relinker:relinker:1.2.3'
そして交換
System.loadLibrary("myLibrary");
と
ReLinker.loadLibrary(context, "mylibrary");
私の状況では、Eclipseのコネクターを介してTomcat 7でJava Webサービスを実行しようとしました。私のラップトップ上のTomcat 7のインスタンスにwarファイルをデプロイすると、アプリはうまく動作しました。アプリには、「IBM DB2 9.5」用のjdbcタイプ2ドライバーが必要です。何らかの奇妙な理由で、Eclispeのコネクターは、IBM DB2環境変数内のパスを表示または使用して、jccクライアントとしてラップトップにインストールされたdllファイルに到達できませんでした。エラーメッセージには、db2jcct2 dllファイルが見つからなかったか、そのdllファイルの依存ライブラリが見つからなかったことが記載されています。最終的に、コネクタを削除して再構築しました。その後、正常に機能しました。この特定のソリューションを他の場所で見つけることができなかったため、ここにドキュメントとしてこのソリューションを追加しています。
私は同じ問題を抱えていたので、ここに掲載されているものをすべて修正して修正しましたが、うまくいきませんでした。私の場合、Cygwinを使用してdllをコンパイルしています。 JVMは仮想CygwinパスでJRE DLLを見つけようとしているようです。 Cygwinの仮想ディレクトリパスをJREのDLLに追加しましたが、現在は動作しています。私は次のようなことをしました:
SET PATH = "/ cygdrive/c/Program Files/Java/jdk1.8.0_45";%PATH%
以前はまったく同じ問題を抱えていましたが、ようやく解決しました。
すべての依存DLLをmylib.dllが保存されている同じフォルダーに入れ、Javaコンパイラーがそれを検出できることを確認します(コンパイルパスにmylib.dllがない場合、エラー報告がありますコンパイル中)。注意する必要がある重要なことは、すべての依存ライブラリがmylib.dllと同じバージョンであることを確認する必要があることです。たとえば、mylib.dllがリリースバージョンである場合、その依存ライブラリすべてのリリースバージョンもそこに配置する必要があります。 。
これが同じ問題に遭遇した他の人を助けることを願っています。
g++ -static
を使用してコンパイルし、静的ライブラリの作成はうまくいきました。ビルドとともに依存ライブラリをバンドルします。