java.lang.UnsatisfiedLinkErrorいいえjava.library.pathに*****。dll


92

Webアプリケーションにカスタムdllファイルをロードするにはどうすればよいですか?私は以下を試しました:

  • system32フォルダー内のすべての必要なDLLをコピーし、それらの1つをServletコンストラクターにロードしようとしましたSystem.loadLibrary
  • とに必要なdllをコピーtomcat_home/shared/libしましたtomcat_home/common/lib

これらのDLLはすべてWEB-INF/libWebアプリケーション内にあります

回答:


154

が機能するため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)を見つけることができません。それが次のようなものを言うなら:PATHjava.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() {
    }

}

1
すべてのdllをSystem32に配置し、System.loadLibrary( "something")を使用することで機能しました。以前System.loadLibrary( "something.dll")をしていた。WEB-INFからすべてのDLLをロードできないのはなぜですか?私はそれがデフォルトですべてのjarをロードすると思います。System32の代わりにWEB-INFから直接これらのDLLをロードするために何ができますか/ java.library.pathでそれらを指定します
Ketan Khairnar '10

2
備考に「bla.dll」ではなく「bla」を使用するための+1- loadLibrary()何が間違っているのかがわからない場合に非常に役立ちます。
MarnixKlooster ReinstateMonica

20
私のシステム(Linuxおよびjava7)では、libプレフィックスが必要です。だからSystem.loadLibrary("foo")必要libfoo.soです。
kristianlm 2013年

2
ありがとう。* .soファイルを含むフォルダーが含まれるようにWindowsの「PATH」を更新したとき、それは私にとってはうまくいきました。
user613114 2014

15

実行時に「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ライブラリパスを変更するで略奪してください。


10

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にあります。


1
この回答はアプリケーションサーバーにとって優れており、この質問では無駄になるため、独自の質問が必要です。
JoshDM

8

を使用System.load()して、それぞれのOSの標準ライブラリフォルダー内のファイルではなく、必要な絶対パスを指定できます。

すでに存在するネイティブアプリケーションが必要な場合は、を使用してくださいSystem.loadLibrary(String filename)。独自のものを提供したい場合は、おそらくload()の方が優れています。

セットで正しく使用loadLibraryすることもできるはずjava.library.pathです。ClassLoader.javaチェックされている両方のパスを示す実装ソース(OpenJDK)を参照してください


ありがとう。負荷の使用は実際にははるかに簡単で直感的なIMHOです。... LoadLibrary関数は、私が何をしたかに関係なく動作するように取得できませんでした
プランカルキュール

2
このソリューションは、独自のネイティブライブラリをロードするライブラリでは機能しません。
ジャスティンスキーズ2014

7

問題が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」という用語を使用しています。)


5

(現在のディレクトリのように)既に存在するディレクトリに関連するファイルをロードする必要がある場合、簡単な解決策は次のとおりです。

File f;

if (System.getProperty("sun.arch.data.model").equals("32")) {
    // 32-bit JVM
    f = new File("mylibfile32.so");
} else {
    // 64-bit JVM
    f = new File("mylibfile64.so");
}
System.load(f.getAbsolutePath());

4

お探しの方へ java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

私も同じ例外に直面していた。私はそれを機能させるためにすべてと重要なことを試しました:

  1. PDF lib.jarの正しいバージョン(私の場合、サーバーランタイムに保持されているバージョンjarが間違っていました)
  2. フォルダーを作成し、その中にpdflib jarを保持し、PATH変数にフォルダーを追加します

Tomcat 6で動作しました。


3
  1. にネイティブlibのパスを追加したと思われる場合は%PATH%、次のコードでテストしてみてください。

    System.out.println(System.getProperty("java.library.path"))

あなたのdllがオンの場合、それはあなたに実際に表示するはずです %PATH%

  1. IDEのアイデアを再起動します。これは、env変数をに追加してセットアップした後に機能するように見えました %PATH%

2

かわいそう!この問題に1日費やしました。この問題を再現する組織がある場合は、ここに書き留めます。

Adamの提案どおりにロードしようとしましたが、AMD64とIA 32の例外に巻き込まれました。いずれにせよ、Adamの(間違いなくベストピック)ウォークスルーに従って作業した後は、最新のjreの64ビットバージョンを用意してください。 JREとJDKが64ビットであり、クラスパスに正しく追加されている。

私の実際の例はここに行きます:unstatisfied link error


0

Windowsの場合、filles(jd2xsx.dll呼び出しとftd2xx.dll)をwindowws / system32フォルダーにロードすると、問題が解決することがわかりました。次に、新しいfd2xx.dllでパラメーターに関連する問題が発生したため、このdllの古いバージョンをロードする必要がありました。私はこれを後で出す必要があります。

注:jd2xsx.dllはftd2xx.dllを呼び出すため、jd2xx.dllのパスを設定するだけでは機能しない場合があります。


0

私は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"
Lokesh Pandey

昨年はJavaを使用していませんが、競合が発生する可能性があるため、ファイルパスに空のスペースを追加しないことをお勧めします
alexventuraio 2018

0

私は同じ問題を抱えていて、エラーはdllの名前変更が原因でした。ライブラリ名がdll内のどこかに書き込まれている可能性もあります。元の名前に戻すと、System.loadLibrary


0

ウィンドウのコマンドラインでjava -XshowSettings:propertiesと記述し、java.library.pathで示されるパスにすべてのファイルを貼り付けるだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.