gpt4 book ai didi

Java Web Start - 使用另一个 native 依赖项加载 native 依赖项

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:36:18 24 4
gpt4 key购买 nike

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

当不使用 Web Start 时,当 native 库位于同一目录时,一切都按预期工作。

但是,Web Start 要求将 native 库打包到 jar 文件中并在 jnlp 文件中引用,我就是这么做的:

  <!-- 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>

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

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

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

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

是否有跨平台的方式来打包和加载依赖于 Java Web Start 中其他原生库的原生库?

最佳答案

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

...
<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 将这些资源提取到一个临时目录中:

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 步要么通知 native JNI 库有关提取依赖项的完整路径,要么临时将当前目录设置为临时目录 tmpDir,加载 JNI 库并将其设置回去。这本身就是一个问题——在 Java 中很难改变当前的工作目录。您可以通过创建另一个从 C 执行此操作的小型实用程序 JNI 库来解决它 [ 1 ].

关于Java Web Start - 使用另一个 native 依赖项加载 native 依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17776507/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com