回答:
が機能するためSystem.loadLibrary()
には、ライブラリ(Windowsの場合、DLL)が、システムプロパティにリストされているパスPATH
またはパスのどこかにある必要がありjava.library.path
ます(そのため、Javaを起動できますjava -Djava.library.path=/path/to/dir
)。
また、ではloadLibrary()
、ライブラリのベース名を.dll
、末尾にを付けずに指定します。したがって、の場合は/path/to/something.dll
、を使用するだけSystem.loadLibrary("something")
です。
また、UnsatisfiedLinkError
取得している正確なものを確認する必要があります。それが次のようなものを言うなら:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
次に、あなたまたはあなたの中でfooライブラリ(foo.dll)を見つけることができません。それが次のようなものを言うなら:PATH
java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V
次に、JavaがアプリケーションのネイティブJava関数を実際のネイティブJava関数にマップできないという意味で、ライブラリ自体に問題があります。
まず、あなたのSystem.loadLibrary()
呼び出しをログに記録して、正しく実行されるかどうかを確認します。例外がスローされるか、実際に実行されるコードパスにない場合は、常にUnsatisfiedLinkError
上記の後者のタイプが表示されます。
補足として、ほとんどの人loadLibrary()
はネイティブメソッドを使用して、クラスの静的初期化ブロックに呼び出しを入れ、常に1回だけ実行されるようにします。
class Foo {
static {
System.loadLibrary('foo');
}
public Foo() {
}
}
loadLibrary()
何が間違っているのかがわからない場合に非常に役立ちます。
lib
プレフィックスが必要です。だからSystem.loadLibrary("foo")
必要libfoo.so
です。
実行時に「java.library.path」変数を変更しても、JVMによって一度だけ読み取られるため、十分ではありません。次のようにリセットする必要があります。
System.setProperty("java.library.path", path);
//set sys_paths to null
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
実行時にJavaライブラリパスを変更するで略奪してください。
Adam Batkinによる最初の回答で解決策が導き出されますが、(Webコンテナーを再起動せずに)Webアプリケーションを再デプロイすると、次のエラーが発生するはずです。
java.lang.UnsatisfiedLinkError: Native Library "foo" already loaded in another classloader
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646)
at java.lang.Runtime.load0(Runtime.java:787)
at java.lang.System.load(System.java:1022)
これは、最初にDLLをロードしたClassLoaderがまだこのDLLを参照しているために起こります。ただし、ウェブアプリは新しいClassLoaderで実行されています。同じJVMが実行されており、JVMは同じDLLへの2つの参照を許可しないため、再読み込みできません。したがって、Webアプリケーションは既存のDLLにアクセスできず、新しいDLLをロードできません。それで……あなたは行き詰まっています。
TomcatのClassLoaderドキュメントには、リロードされたWebアプリケーションが新しい分離されたClassLoaderで実行される理由と、この制限を回避する方法(非常に高いレベル)の概要が示されています。
解決策は、Adam Batkinのソリューションを少し拡張することです。
package awesome;
public class Foo {
static {
System.loadLibrary('foo');
}
// required to work with JDK 6 and JDK 7
public static void main(String[] args) {
}
}
次に、このコンパイルされたクラスを含むjarをTOMCAT_HOME / libフォルダーに配置します。
これで、Webアプリケーション内で、Tomcatがこのクラスを参照するように強制する必要があります。これは、次のように簡単に実行できます。
Class.forName("awesome.Foo");
これで、DLLは共通のクラスローダーに読み込まれ、再デプロイされた後でもwebappから参照できます。
理にかなっていますか?
動作する参照コピーは、Googleコードのstatic-dll-bootstrapperにあります。
を使用System.load()
して、それぞれのOSの標準ライブラリフォルダー内のファイルではなく、必要な絶対パスを指定できます。
すでに存在するネイティブアプリケーションが必要な場合は、を使用してくださいSystem.loadLibrary(String filename)
。独自のものを提供したい場合は、おそらくload()の方が優れています。
セットで正しく使用loadLibrary
することもできるはずjava.library.path
です。ClassLoader.java
チェックされている両方のパスを示す実装ソース(OpenJDK)を参照してください
問題がSystem.loadLibraryが問題のDLLを見つけられないことである場合、1つの一般的な誤解(Javaのエラーメッセージによって強化される)は、システムプロパティjava.library.pathが答えであるというものです。システムプロパティjava.library.pathをDLLがあるディレクトリに設定すると、System.loadLibraryは実際にDLLを見つけます。ただし、DLLが他のDLLに依存している場合、よくあることですが、依存するDLLの読み込みはオペレーティングシステムによって完全に管理されているため、java.library.pathはjava.libraryをまったく認識していません。道。したがって、ほとんどの場合、JVMを起動する前に、java.library.pathをバイパスし、DLLのディレクトリをLD_LIBRARY_PATH(Linux)、DYLD_LIBRARY_PATH(MacOS)、またはPath(Windows)に追加することをお勧めします。
(注:DLLまたは共有ライブラリの一般的な意味で「DLL」という用語を使用しています。)
お探しの方へ java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path
私も同じ例外に直面していた。私はそれを機能させるためにすべてと重要なことを試しました:
Tomcat 6で動作しました。
かわいそう!この問題に1日費やしました。この問題を再現する組織がある場合は、ここに書き留めます。
Adamの提案どおりにロードしようとしましたが、AMD64とIA 32の例外に巻き込まれました。いずれにせよ、Adamの(間違いなくベストピック)ウォークスルーに従って作業した後は、最新のjreの64ビットバージョンを用意してください。 JREとJDKが64ビットであり、クラスパスに正しく追加されている。
私の実際の例はここに行きます:unstatisfied link error
私はMac OS X YosemiteとNetbeans 8.02を使用していますが、同じエラーが発生し、簡単な解決策は上記のようになりました。これは、プロジェクトにネイティブライブラリを含める必要がある場合に便利です。Netbeansの場合は次のようにします。
1.- Right click on the Project
2.- Properties
3.- Click on RUN
4.- VM Options: java -Djava.library.path="your_path"
5.- for example in my case: java -Djava.library.path=</Users/Lexynux/NetBeansProjects/NAO/libs>
6.- Ok
誰かのお役に立てれば幸いです。私が解決策を見つけたリンクはここにあります: java.library.path –それは何で、どのように使用するか
VM Options: java -Djava.library.path="your_path"
私は同じ問題を抱えていて、エラーはdllの名前変更が原因でした。ライブラリ名がdll内のどこかに書き込まれている可能性もあります。元の名前に戻すと、System.loadLibrary