首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java Web Start -使用另一个本机依赖项加载本机依赖项

问Java Web Start -使用另一个本机依赖项加载本机依赖项
EN

Stack Overflow用户
提问于 2013-07-22 04:20:05
回答 1查看 2.3K关注 0票数 8

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

如果不使用Web Start,则当本机库位于同一目录中时,一切都会按预期运行。

然而,Web Start要求将本地库打包到jar文件中并在jnlp文件中引用,我做到了:

代码语言:javascript
复制
  <!-- 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>

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

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

代码语言:javascript
复制
System.loadLibrary("commonLib");
System.loadLibrary("myNativeLib");

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

有没有一种跨平台的方法来打包和加载依赖于Java Web Start中其他本机库的本地库?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-25 05:55:25

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

代码语言:javascript
复制
...
<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将这些资源解压缩到一个临时目录中:

代码语言:javascript
复制
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中,很难改变当前的工作目录。你可以通过创建另一个小的实用程序JNI库来解决这个问题,这个库通过[1]从C实现。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17776507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档