无法使用激活器加载本机库(Play 框架)

Posted

技术标签:

【中文标题】无法使用激活器加载本机库(Play 框架)【英文标题】:fail to load a native library using activator (Play Framework) 【发布时间】:2015-10-15 18:14:04 【问题描述】:

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

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

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

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

fork := true

以下测试在 IDE 和 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 的启动生命周期中加载原生库。

object Global extends GlobalSettings 

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


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

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 如下所示:

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 会分叉 JVM 并为 both test run 上下文设置java.library.path。关于我做错了什么的任何线索?

新信息

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

【问题讨论】:

【参考方案1】:

我找到了问题的解决方案here。

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

创建一个类似的类:

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

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

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 框架)的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.IllegalArgumentException:无法加载本机库

LibVLCSharp:“无法加载所需的本机库。”

Play framework 2.4 打包后无法加载图片(404 source not found)

大家好!谷歌play 怎么添加本地音乐啊????

在 Play Framework 2.3.8 中使用 SORM

无法获得在grails 3中执行的本机库(.so)