Java:重用已加载的本机库?

时间:2017-09-15 18:29:24

标签: java eclipse opencv unsatisfiedlinkerror max-msp-jitter

免责声明 不是以英语为母语的人,如果需要,请随时修改。

我遇到的问题与此处解释的类似: 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

    Max / MSP允许用户通过将一些称为 externals 的对象连接在一起来组装Patch,其中大多数都是用C编码的,但您也可以用Java创建外部。为此,您需要通过名为“mxj”的对象实例化它们。例如,如果我的Java类名为TestOpenCV,我将创建一个框并将“mxj TestOpenCV”放入其中。

    OpenCV似乎正确实现,例如,我可以实例化一个Mat对象并将其内容发布到Max控制台。

    当我更改mxj对象的Java代码时出现问题。要更新我的对象,我将其删除并重新创建它。然后,出现了解释here的相同问题......

    enter image description here

    Max控制台返回此错误消息:

      

    java.lang.UnsatisfiedLinkError:原生图书馆    C:\ Windows \ System32 \ opencv_java300.dll已经加载到另一个中   java.lang.ClassLoader.loadLibrary1(未知来源)的类加载器   java.lang.ClassLoader.loadLibrary0(未知来源)at   java.lang.ClassLoader.loadLibrary(未知来源)at   java.lang.Runtime.loadLibrary0(未知来源)at   java.lang.System.loadLibrary(未知来源)at   OpenCVClassLoad.loadNativeLibrary(OpenCVClassLoad.java:5)at at   TestOpenCV。(TestOpenCV.java:22)(mxj)无法分配实例   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代码,删除Max中的对象并创建一个新对象,则会出现错误......

    问题

    有许多SO问题解决了相同类型的概率,但上下文总是不同的,很难弄清楚要做什么,尤其是我对Java的基本知识。

    解决方法应该是简单地重用已经加载的库,不是吗?但是如何实现呢?因为如果我检查库已经被加载,我会使用Try / Catch来做,如果我什么都不做的话。外部的行为就像图书馆从未加载过......

    如何重用该本机库? (当然,欢迎任何替代解决方案)

1 个答案:

答案 0 :(得分:0)

删除OpenCVClassLoad.loadNativeLibrary();方法中的第二个bang() 。在普通的Java应用程序中,static块中的代码只执行一次。

或者,您可以specify the native library location in Eclipse而不是通过Java源代码加载库。