无法使用激活器加载本机库(Play 框架) [英] fail to load a native library using activator (Play Framework)

查看:29
本文介绍了无法使用激活器加载本机库(Play 框架)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的 Play 2.4.x 应用程序中加载本机库.我编写了一个简单的测试,它在 IDE (IntelliJ) 和 SBT 中都可以正常工作.在这两种情况下,我都设置了 java.library.path 以运行测试.

I'm trying to load a native library in my Play 2.4.x application. I have written a simple test that works fine both in the IDE (IntelliJ) and in SBT. In both case I'm setting the java.library.path to get the tests to run.

在 IDE 中,我在测试运行配置中设置了 -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64.

In the IDE, I set -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64 in the test run configuration.

根据 sbt 文档,我的 build.sbt 正在分叉 JVM 并设置 java.library.path.

As per the sbt documentation, my build.sbt is forking the JVM and setting the java.library.path.

javaOptions += "-Djava.library.path=/home/aczerwon/dev/lindoapi/bin/linux64"

fork := true

以下测试在 IDE 和 activator test 中都顺利通过.

The following test passes just fine in both the IDE and from activator test.

class LindoApiSpec extends Specification {

  System.loadLibrary("lindojni")

  "The Lindo API" should {

    "have a valid license" in {
      val lindo = new LindoEnvironment()
      lindo.apiVerion() must beSuccessfulTry.withValue("LINDO API Version 9.0.2120.225")
    }

}

在测试环境之外时,我会在 Play 的启动生命周期中加载原生库.

When outside of the testing context, I load the native library in Play's startup lifecycle.

object Global extends GlobalSettings {

  override def beforeStart(app: Application) = {
    System.loadLibrary("lindojni")
  }

}

当我从 webapi (activator ~run) 调用相同的方法时,我收到 UnsatisfiedLinkError 错误.

When I call that same method from the webapi (activator ~run), I'm getting an UnsatisfiedLinkError error.

1) Error injecting constructor, java.lang.UnsatisfiedLinkError: no lindojni in java.library.path
  at play.api.GlobalPlugin.<init>(GlobalSettings.scala:262)
  at play.api.GlobalPlugin.class(GlobalSettings.scala:262)
  while locating play.api.GlobalPlugin

web api 如下所示:

The web api looks like this:

class OptimizationApi extends Controller {

  def version() = Action {
    val lindo = new LindoEnvironment()
    lindo.apiVerion() match {
      case Success(version) => Ok(version)
      case Failure(e) => BadRequest(e.getMessage)
    }
  }

}

我假设我的 build.sbt 会 fork JVM 并为 both test 和设置 java.library.path 运行上下文.关于我做错了什么的任何线索?

I assumed that my build.sbt would fork the JVM and set the java.library.path for both test and run contexts. Any clues as to what I'm doing wrong?

新信息

当我启动 activator -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64 或设置 JAVA_OPTS 时,调用 System.loadLibrary(...) 在启动生命周期中经过.我仍然收到 UnsatisfiedLinkError,但是稍后当我通过 JNI 调用本机库时会发生这种情况.很奇怪.

When I start activator -Djava.library.path=$USER_HOME$/dev/lindoapi/bin/linux64 or set JAVA_OPTS, the call to System.loadLibrary(...) in the startup lifecycle passes. I still get the UnsatisfiedLinkError, but it happens later when I make a call to the native library via JNI. Very strange.

推荐答案

我找到了问题的解决方案 这里.

I found a solution to the issue here.

本机库及其对应的 java 必须在同一个类加载器中.

The native library and its java counterpart must be in the same class loader.

创建一个类似的类:

public final class PlayNativeLibraryLoader {
    public static void load(String libraryPath) {
        System.load(libraryPath);
    }
}

现在您可以在 Play 启动生命周期中使用它.

And now you can use it in the Play startup lifecycle.

object Global extends GlobalSettings {

  override def beforeStart(app: Application) = {
    PlayNativeLibraryLoader.load(app.getFile("./lib/lindoapi/linux64/liblindojni.so").getPath)
    Logger.info("Lindo native library loaded")
  }

}

这篇关于无法使用激活器加载本机库(Play 框架)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆