【问题标题】:Play Framework - System.loadLibrary() only once per threadPlay Framework - System.loadLibrary() 每个线程只有一次
【发布时间】:2013-11-18 08:30:21
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: java c++ scala opencv playframework


    【解决方案1】:

    似乎没有问题 - “此命令必须在每个 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 可用于 不同的线程,因为引用计数操作使用 特定于架构的原子指令。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-17
    • 2016-03-05
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 2016-03-19
    • 2019-08-09
    相关资源
    最近更新 更多