2017-09-15 10 views
0

免責事項英語のネイティブスピーカーではなく、必要に応じて編集してください。 java.lang.UnsatisfiedLinkError: Native Library XXX.so already loaded in another classloaderJava:既にロードされているネイティブライブラリを再利用しますか?

私はuser2543253の答えを追跡しようとしている:

は、私は1つが、ここで説明したという同様の問題を抱えています。しかし、私は本当にJavaの知識が不足しており、コンテキストは少し異なります。

リンク

  1. .dll already loaded in another classloader?この質問にも関連すると思われます。
  2. https://github.com/PatternConsulting/opencv/issues/7類似しています。
  3. https://cycling74.com/articles/mxj-class-loadingはMXJ

コンテキスト

編集のクラスローダの動作について説明します。そのコンテキストが本当に重要であるならば、リンク1.

で説明したのと同じ問題があると思わわからないが

私はOpenCVをMax/MSPというアプリケーションの中で使いたいと思っています。

アイデアを与えるためには、それは次のようになります。

enter image description here

マックス/ MSPは、ユーザが見た目と呼ばれて一緒にいくつかのオブジェクトをケーブル接続することにより、パッチを組み立てることができ、それらのほとんどはCでコーディングされていますJavaで外観を作成することもできます。これを行うには、 "mxj"というオブジェクトを通してそれらをインスタンス化する必要があります。たとえば、私のJavaクラスがTestOpenCVと呼ばれる場合、ボックスを作成し、 "mxj TestOpenCV"を内部に配置します。

OpenCVが正しく実装されているようです。たとえば、Matオブジェクトをインスタンス化してそのコンテンツをMaxコンソールに投稿することができます。

mxjオブジェクトのJavaコードを変更すると問題が発生します。私のオブジェクトを更新するには、オブジェクトを削除してもう一度再作成します。その後、hereが表示された説明と同じ問題...

enter image description here

マックスコンソールは、このエラーメッセージを返す:

java.lang.UnsatisfiedLinkError: Native Library C:\Windows\System32\opencv_java300.dll already loaded in another classloader at java.lang.ClassLoader.loadLibrary1(Unknown Source) at java.lang.ClassLoader.loadLibrary0(Unknown Source) at java.lang.ClassLoader.loadLibrary(Unknown Source) at java.lang.Runtime.loadLibrary0(Unknown Source) at java.lang.System.loadLibrary(Unknown Source) at OpenCVClassLoad.loadNativeLibrary(OpenCVClassLoad.java:5) at TestOpenCV.(TestOpenCV.java:22) (mxj) unable to alloc instance of TestOpenCV

私は

を試してみました何を私がuser2543253の答えを実装してみました。彼はネイティブライブラリをインポートしてJARとしてエクスポートする小さなクラスを作成するようにアドバイスします。だから私は、新しいEclipseプロジェクトは、私がそのプロジェクトにOpenCVのJARを追加し、JARとしてそれをエクスポートし、それ

import org.opencv.core.Core; 

public class OpenCVClassLoad { 
    public static void loadNativeLibrary() { 
    System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 
    } 
} 

にソースファイルを追加作成しました。

は、その後、私はuser2543253を説明するものに応じて自分のコードを変更(より多くのコードは、私は必要不可欠そこに保たれている):もちろん

import com.cycling74.max.*; 
import org.opencv.core.Core; 
import org.opencv.core.CvType; 
import org.opencv.core.Mat; 
import org.opencv.core.Scalar; 

public class TestOpenCV extends MaxObject { 
    static { 
    // System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 
    OpenCVClassLoad.loadNativeLibrary(); 
    } 

    public TestOpenCV(Atom[] args) 
    { 
    // ... 
    } 

    public void notifyDeleted() 
    { 
    // ... 
    } 

    public void bang() { 
    // Executed when I trig the little bang button you can see 

    Mat m = new Mat(5, 9, CvType.CV_8UC4, new Scalar(0)); 
    post("OpenCV Mat: " + m); 

    Mat mr1 = m.row(1); 
    mr1.setTo(new Scalar(1)); 

    Mat mc5 = m.col(3); 
    mc5.setTo(new Scalar(5)); 

    post("OpenCV Mat data:\n" + m.dump()); 
    } 
} 

が、それは正しく、そのプロジェクトを構築するために、少し奇妙だIビルド・パスにOpenCVのからJARを保持:あなたが見ることができるように

enter image description here

が、私はまた、プロジェクトのビルド・パスに小さなクラスを追加しました。 これらの変更をすべて行った後、mxjオブジェクトstilleが最初に正しくロードされ、bang()メソッドは引き続き動作しますが、問題はそのまま残ります。実際には、過去の状況からは何も変わりません:私は、Javaコードを変更マックスでオブジェクトを削除するとエラーが表示され、新しいものを作成した場合...

質問

たくさんのがあります同じタイプの問題に対処するためのSOの質問ですが、コンテキストは常に異なっており、特にJavaについての私の基礎知識があれば、何をすべきかを理解するのは難しいです。

回避策は、すでにロードされているライブラリを単に再利用することです。どのようにこれを達成するために?ライブラリが既にロードされていることを確認すると、何もしなければ、Try/Catchを使ってライブラリをロードします。図書館が一度もロードされていなかった場合のように、外見は機能します。

そのネイティブライブラリを再利用するにはどうすればいいですか?

答えて

0

だけは、あなたのbang()法第二OpenCVClassLoad.loadNativeLibrary();を削除する(もちろん、これに対する任意の代替ソリューションは大歓迎です)。プレーンなJavaアプリケーションでは、staticブロックのコードは1回だけ実行されます。

また、Javaソースコードでライブラリをロードする代わりに、specify the native library location in Eclipseとすることもできます。

+0

あなたの最初の解決策はうまくいきません。すでに試してみましたが、説明はおそらくhttps://cycling74.com/articles/mxj-class-loadingです。 JAVAコードを変更すると、再コンパイルされます。したがって、それはより最近のクラスファイルを持っています、MXJはそれを検出し、新しいクラスローダーを作成します。私はあなたの代替ソリューションを読むでしょう、私はまだそれを見つけませんでした。そのリンクを追加するために投稿を編集し、2番目のOpenCVClassLoad.loadNativeLibrary()を削除しました。それは役に立たない。 –

+0

私は代わりの解決法を試しましたが、それは助けに見えません。実際、私はそれがどのように助けてくれるのか見当たりません。問題はクラスローダーから来ています。ネイティブライブラリの場所を設定することで、System.loadLibrary()を使用する必要はもうありません。またはクラスローダー? –

+0

はい、ネイティブライブラリの場所(= '-Djava.library.path = ...')を設定するか、実行時に 'System.loadLibrary()'でライブラリをロードしてください。 2番目のケースでは、新しいException()。printStackTrace();をコードに追加して、コードの実行場所と頻度を調べることができます。 – howlger

関連する問題