0

我正在使用 Play Framework 2.1 编写一个使用 OpenCV (2.4.6) 库的 web 应用程序。我在编译 OpenCV 并获得最终的 .jar 时没有任何问题,但是在OpenCV的 Java/Scala 教程中有一句话让我担心:

注意对 的调用System.loadLibrary(Core.NATIVE_LIBRARY_NAME)。在使用任何本机 OpenCV 方法之前,每个 Java 进程必须只执行一次此命令。如果你不调用它,你会得到 UnsatisfiedLink 错误。如果您在加载 OpenCV 时尝试加载它,也会出现错误。

我知道 Play Framework 是多线程的,并且线程在请求​​之间被重用。loadLibrary当产生每个单独的线程时,我有没有办法调用该函数?还是我误解了线程池的工作原理,我应该每个请求加载一次库?这里的正确方法是什么?

[编辑:] 我发现我可以将System.loadLibrary代码放在全局配置类中,这将使所有线程共享库。该库不是线程安全的,所以我认为如果我这样做只是等待发生的意外......

4

1 回答 1

0

似乎没有问题 - “这个命令必须每个 Java进程只执行一次” - 在应用程序启动时调用它一次就足够了,你不必担心不同的线程

奖励:可以检查库是否已经加载(即使完全没有必要),即:

 def loadedLibs: Seq[String] = {
    val libs = classOf[ClassLoader].getDeclaredField("loadedLibraryNames")
    libs.setAccessible(true)
    import scala.collection.JavaConverters._
    libs.get(ClassLoader.getSystemClassLoader())
      .asInstanceOf[java.util.Vector[String]]
      .asScala
  }

  def loadOpenCVOnDemand(): Unit = {
    val isLoaded = loadedLibs.map(str => str contains "opencv").reduce((x, y) => x || y)
    if(!isLoaded) {
      System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
    }
  }

另一个问题是是否可以同时调用本机库的函数。在 OpenCV 中,这根本不是问题:

当前的 OpenCV 实现是完全可重新输入的。即同一个函数,同一个类实例的同一个常量方法,或者不同类实例的同一个非常量方法,可以从不同的线程调用。此外,相同的 cv::Mat 可以在不同的线程中使用,因为引用计数操作使用特定于体系结构的原子指令。

于 2013-11-06T23:58:08.557 回答