无法使用激活器加载本机库(Play框架) [英] fail to load a native library using activator (Play Framework)
问题描述
我正在尝试在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
网络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将派生JVM,并为两者 test
和 run
上下文设置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.
创建一个类似于以下内容的类:
Create a class similar to:
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屋!