2017-09-15 27 views
0

免責聲明母語不是英語,如果需要,隨意編輯。Java:重新使用已加載的本機庫?

我有一個類似的問題是,一個在這裏解釋: java.lang.UnsatisfiedLinkError: Native Library XXX.so already loaded in another classloader

我試圖按照user2543253的答案。但是我真的對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
  4. 的類加載器的行爲

語境

編輯:不知道這方面是非常重要的,這似乎是同樣的問題,在鏈接描述1

我想在名爲Max/MSP的應用程序中使用OpenCV。

舉一個想法,它看起來像這樣:

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項目添加源文件,它

import org.opencv.core.Core; 

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

我加入OpenCV的JAR到該項目,並出口它作爲一個JAR。

然後我根據什麼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()); 
    } 
} 

當然,不過這是一個有點怪異,以便正確地構建項目我從保持了OpenCV的JAR在構建路徑:

enter image description here

正如你所看到的,我還添加了小小的類項目構建路徑。 經過所有這些修改後,mxj對象stille首次正確加載,並且bang()方法仍然有效,但問題仍然存在。事實上,它並沒有任何東西從過去的情況發生變化:如果我修改了Java代碼,刪除最大的對象,並創建一個新的,出現錯誤...

問題

有很多的SO問題涉及相同類型的概率,但上下文總是不同,並且很難弄清楚該怎麼做,特別是使用我對Java的基本知識。

解決方法應該是簡單地重用已加載的庫,否?但如何實現這一目標?因爲如果我檢查圖書館已經被加載,我使用Try/Catch來做,如果我什麼也不做。外部的行爲,如果圖書館從未被加載...

如何重用該本地庫? (當然,歡迎任何替代解決方案)

回答

0

只需在您的bang()方法中刪除第二個OpenCVClassLoad.loadNativeLibrary();。在普通的Java應用程序中,static塊中的代碼僅執行一次。

或者,您可以specify the native library location in Eclipse而不是通過Java源代碼加載庫。

+0

不幸的是,你的第一個解決方案是行不通的,我已經試過了,可能是這裏的解釋:https://cycling74.com/articles/mxj-class-loading。當我更改JAVA代碼時,它被重新編譯。因此,它有一個更新的類文件,MXJ檢測它並創建一個新的類加載器。我將閱讀您的替代解決方案,但我還沒有找到。我編輯帖子添加該鏈接並刪除了第二個OpenCVClassLoad.loadNativeLibrary();這是沒用的。 –

+0

所以我嘗試了另一種解決方案,但似乎沒有幫助。事實上,我不明白它應該如何幫助,問題來自於類加載器。你的意思是通過設置本地庫的位置,我不再需要使用System.loadLibrary();或類加載器? –

+0

是,或者設置本地庫位置(='-Djava.library.path = ...')或者在運行時通過'System.loadLibrary()'加載庫。在第二種情況下,您可以在代碼中添加新的Exception()。printStackTrace();來查找代碼執行的位置和頻率。 – howlger