Java Web Start - 使用另一个本机依赖项加载本机依赖项 [英] Java Web Start - load native dependency with another native dependency

查看:43
本文介绍了Java Web Start - 使用另一个本机依赖项加载本机依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Java Web Start 来启动依赖于某些第三方本机库的 Java 应用程序.这些本机库随后使用 LoadLibrary/dlopen 加载另一个本机库 (commonLib) 作为它们的依赖项.

I am using Java Web Start to launch a Java application that depends on some third party native libraries. These native libraries then subsequently load another native library (commonLib) as their dependency using LoadLibrary/dlopen.

当不使用 Web Start 时,当本机库位于同一目录中时,一切都按预期工作.

When not using Web Start, everything works as expected when the native libraries are located in the same directory.

但是,Web Start 要求将本机库打包在 jar 文件中并在 jnlp 文件中引用,我这样做了:

Web Start, however, requires the native libraries to be packed in a jar file and referenced in the jnlp file, which I did:

  <!-- Windows OS -->
    <resources os="Windows">
        <nativelib href="native/native-windows.jar" />
    </resource>

  <!-- Linux OS -->
    <resources os="Linux">
        <nativelib href="native/native-linux.jar" />
    </resources>

  <!-- Mac OSX -->
    <resources os="Mac OS X">
        <nativelib href="native/native-osx.jar"/>   
    </resources>

本机库加载正常,但无法加载其依赖项 commonLib - C++ LoadLibrary/dlopen 调用失败,因为该文件位于某个 jar/cache 文件夹中,而不是在当前库搜索路径中.

The native libraries load fine but they fail to load their dependency commonLib - the C++ LoadLibrary/dlopen call fails because the file is present in some jar/cache folder not on the current library search path.

在 Windows 上,我能够通过在尝试加载 JNI 库之前在 Java 中预加载 commonLib 来解决这个问题,如下所示:

On Windows, I was able to solve this problem by pre-loading commonLib in Java before trying to load the JNI library, like so:

System.loadLibrary("commonLib");
System.loadLibrary("myNativeLib");

但是,这种方法在 OS X 上不起作用 - 本机代码中的 dlopen 失败.dlopen 显然不够聪明,如果库已经加载,它不会尝试再次加载.

However, this approach doesn't work on OS X - dlopen in the native code fails. dlopen is apparently not smart enough not to try to load the library again if it is already loaded.

是否有一种跨平台的方式可以在 Java Web Start 中打包和加载依赖于其他本机库的本机库?

Is there a cross-platform way to pack and load native libraries that depend on other native libraries in Java Web Start?

推荐答案

我找到了一个(丑陋的)解决方法.诀窍是将依赖库 (commonLib) 打包到一个简单的资源 jar 并将其添加到 jnlp 文件中:

I was able to find an (ugly) workaround. The trick is to pack the dependent libraries (commonLib) to a simple resource jar and add it to the jnlp file:

...
<resources os="Windows">
  <jar href="native/deps-windows.jar" />
</resources>
<resources os="Linux">
  <jar href="native/deps-linux.jar" />
</resources>
<resources os="Mac OS X">
  <jar href="native/deps-osx.jar" />
</resources>
...

第二步是使用Java将这些资源提取到一个临时目录中:

Step two is to extract these resources using Java into a temporary directory:

String tmpDir = System.getProperty("java.io.tmpdir");
if (!tmpDir.endsWith("/") && !tmpDir.endsWith("\\"))
    tmpDir += "/";
String resource = "commonDir.dll"; // Adjust accordingly to current OS, omitted for brevity
InputStream is = loader.getResourceAsStream(resource);
if (is == null) {
    // Handle error - resource not found
    return;
}
try {
    FileOutputStream os = new FileOutputStream(tmpDir + resource);
    byte[] buffer = new byte[1024*1024];
    int len = is.read(buffer);
    while (len != -1) {
        os.write(buffer, 0, len);
        len = is.read(buffer);
    }
    os.close();
    is.close();
    System.out.println("Extracted " + resource + " to " + tmpDir);
} catch(IOException ex) {
    // Handle the exception - cannot write to temp directory
    System.out.println("Could not extract resource " + resource + " to " + tmpDir + ": " + ex.getMessage());
}

第 3 步是将提取的依赖项的完整路径通知本机 JNI 库,或者将当前目录临时设置为临时目录 tmpDir,加载 JNI 库并将其设置回来.这本身就是一个问题 - 在 Java 中很难更改当前工作目录.您可以通过创建另一个从 C 执行此操作的小型实用程序 JNI 库来解决此问题 [1].

Step 3 is either to inform the native JNI library about the full path to the extracted dependency, or to temporarily set current directory to the temp directory tmpDir, load the JNI library and set it back. This is a problem by itself - in Java it is hard to change the current working directory. You may solve it by creating another small utility JNI library that does that from C though [1].

这篇关于Java Web Start - 使用另一个本机依赖项加载本机依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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