UnsatisfiedLinkError: Как загрузить нативную библиотеку opencv при запуске приложения play? - PullRequest
3 голосов
/ 04 апреля 2019

Я запускаю приложение Play Framework, используя OpenCV с Scala.Когда я запускаю приложение, я получаю UnsatisfiedLinkError от VideoCapture, так как я могу правильно загрузить библиотеку opencv?

Когда я запускаю тест с использованием классов из opencv, все работает правильно.Я всегда устанавливаю System.loadLibrary (Core.NATIVE_LIBRARY_NAME) и правильно определяю параметр java.path.library.Но когда я запускаю приложение play, это не работает как с тестами.

Из других постов люди решали эту проблему, используя абстрактный класс GlobalSetting из play и загружая библиотеку в методе beforeStart ().,Но это устарело, и теперь Play рекомендует сделать обязательную привязку.Я уже пытался создать загрузчик Eager для первого запуска при запуске сервера, на котором я загружаю библиотеку таким же образом, как я запускаю тесты.Код в этом классе запускается первым, как и должно быть, но это не спасает мою проблему.

Я также пытался загрузить библиотеку в различные контроллеры, которые у меня есть, и в классе, где я использую VideoCapture () но ничего не работает.Кроме того, я попытался создать задачу sbt, в которую я загрузил библиотеку, но она не работала.

class EagerLoaderModule extends AbstractModule {
  override def configure(): Unit = bind(classOf[StartUpService]).asEagerSingleton()
}
final class StartUpService {

  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) {
      try {
        println("hey there dude")
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
        println("ksdfjsdkfh")
      } catch {
        case e: UnsatisfiedLinkError =>
          println("Loading Library OPENCV")
          System.loadLibrary("opencv_java345")
        //      e.printStackTrace()
      }
    }
  }

  loadOpenCVOnDemand()

}

Я получаю сообщение об ошибке: java.lang.UnsatisfiedLinkError: org.opencv.videoio.VideoCapture.VideoCapture_1 (Ljava / lang / String;) J , и я знаю, что это потому, что System.loadLibrary (Core.NATIVE_LIBRARY_NAME) не работает правильно, но как я могу заставить его работать или гдея должен установить так, чтобы приложение загружало библиотеку правильно?

1 Ответ

2 голосов
/ 08 апреля 2019

Поддержка встроенной библиотеки в режиме разработки (запуск воспроизведения) # 2212 определяет проблему как:

Когда libopencv_java загружается из управляемого кода play-sbt-plugin, оназагружается в ReloadableClassLoader, но opencv - *. jar уже находится в PlayDependencyClassLoader.Кажется, JDK не нравится такой раскол.Итак, нативная библиотека и ее Java-аналог должны (должны?) Находиться в одном загрузчике классов .Одно из решений состоит в том, чтобы переместить вызовы load / loadLibrary из проекта на основе Play в отдельный jar, а затем добавить этот jar в качестве зависимости проекта.

В качестве обходного пути попробуйте импортировать play-native-loader

libraryDependencies += "com.typesafe.play" %% "play-native-loader" % "1.0.0"

и загрузите библиотеку с NativeLoader.load вместо System.loadLibrary, например,

NativeLoader.load(Core.NATIVE_LIBRARY_NAME)

play-opencv-native-example isрабочий пример.

...