用另一个本地依赖项加载本地依赖项

用另一个本地依赖项加载本地依赖项

本文介绍了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库通知所提取依赖项的完整路径,或者将当前目录临时设置为temp目录tmpDir,加载JNI库并将其重新设置.这本身就是一个问题-在Java中,很难更改当前的工作目录.您可以通过创建另一个小型实用程序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-用另一个本地依赖项加载本地依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-13 10:26