【问题标题】:Java : Reuse a native library already loaded?Java:重用已加载的本机库?
【发布时间】:2018-02-24 23:56:30
【问题描述】:

免责声明母语不是英语,如有需要,请随时编辑。

我遇到了与此处解释的类似问题: 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 的类加载器行为

上下文

编辑:不确定该上下文是否真的很重要,这似乎与链接 1 中描述的问题相同。

我想在一个名为 Max/MSP 的应用程序中使用 OpenCV。

给出一个想法,它看起来像这样:

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

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

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

最大控制台返回此错误消息:

java.lang.UnsatisfiedLinkError: 本机库 C:\Windows\System32\opencv_java300.dll 已经加载到另一个 类加载器在 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(未知来源)在 java.lang.System.loadLibrary(未知来源)在 OpenCVClassLoad.loadNativeLibrary(OpenCVClassLoad.java:5) 在 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 保留在构建路径中:

如您所见,我还在项目构建路径中添加了小类。 在所有这些修改之后,mxj 对象第一次正确加载并且 bang() 方法仍然有效,但问题仍然存在。实际上它并没有改变过去的情况:如果我修改Java代码,删除Max中的对象并创建一个新对象,就会出现错误......

问题

有很多 SO 问题涉及相同类型的问题,但上下文总是不同的,很难弄清楚该怎么做,尤其是在我对 Java 的基本知识的情况下。

解决方法应该是简单地重用已经加载的库,不是吗?但如何做到这一点?因为如果我检查库是否已经被加载,我会使用 Try / Catch 来完成,如果我什么都不做的话。外部行为就像从未加载过库一样......

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

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • 不幸的是,您的第一个解决方案不起作用,我已经尝试过,解释可能在这里:cycling74.com/articles/mxj-class-loading。当我更改 JAVA 代码时,它会重新编译。因此,它有一个更新的类文件,MXJ 检测到它并创建一个新的类加载器。我会阅读你的替代解决方案,我还没有找到那个。我编辑了帖子以添加该链接并删除了第二个 OpenCVClassLoad.loadNativeLibrary();这是没用的。
    • 所以我尝试了替代解决方案,但似乎没有帮助。实际上我看不出它应该如何帮助,问题来自类加载器。你的意思是通过设置本机库位置,我不再需要使用 System.loadLibrary();还是类加载器?
    • 是的,要么设置本机库位置 (= -Djava.library.path=...),要么在运行时通过 System.loadLibrary() 加载库。在第二种情况下,您可以将new Exception().printStackTrace(); 添加到您的代码中,以了解您的代码执行的位置和频率。
    • 我试图在任何我可以设置的地方设置本地库位置:D 没有任何效果,它的行为就像找不到 dll 这可能是这种情况...... java.lang.UnsatisfiedLinkError: org.opencv .core.Mat.n_Mat(IIIDDDD)J 这样做,我不使用 System.loadLibrary(),你是不是我不需要做任何其他事情?上面评论中的链接文章指出,每次修改类文件时,Max/MSP 将使用新的类加载器,但之前加载的 Native lib 将保留在内存中。不是 100% 确定,但这就是我目前的看法……
    • 你能在没有System.loadLibrary()putting your DLL in the support directory的情况下试试吗?
    猜你喜欢
    • 1970-01-01
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-25
    • 2016-04-20
    • 2012-07-31
    • 1970-01-01
    相关资源
    最近更新 更多