【问题标题】:How to unzip a library to a temporary directory, load it and all of its dependencies from that directory如何将库解压缩到临时目录,从该目录加载它及其所有依赖项
【发布时间】:2011-12-05 20:07:27
【问题描述】:

基本上我想将共享对象的集合压缩到一个 jar 文件中,在运行时将它们解压缩到一个临时目录,然后从那里加载。比如说我有图书馆:

  • libApp.so
  • libBasicPlugin.so => libApp.so
  • libPlugin1.so => libApp.so, libBasicPlugin.so, libPlugin2.so
  • libPlugin2.so => libApp.so, libBasicPlugin.so

Java 将它们解压缩到任意唯一的临时目录 $USER_HOME/.my-app/2011_12_05_001/,然后加载 libApp.so,然后使用 dlopen 加载 libPlugin1 和 libPlugin2(未显式加载 libBasicPlugin)。问题是 libPlugin1 不知道在哪里可以找到 libBasicPlugin 和 libPlugin2。

以下是我尝试/考虑过的各种解决方案:

  1. 在调用 Java 之前,将库放在已知位置并在 sh 文件中设置 LD_LIBRARY_PATH。这可行,但无法将库打包到 jar 中
  2. 使用 Java 的 System.load 来“预加载”依赖项。这是我看到的建议的方法,但只有在您先验地知道要加载哪些插件并知道它们的依赖项时,这似乎才有效。除非您遍历目录中的所有文件,否则加载它们直到您停止收到 UnsatisfiedLinkExceptions...
  3. 以某种方式告诉共享对象其依赖项将位于同一目录中(通过 DT_RPATH?)。这是我认为在理想世界中我想要的,但似乎你能做的最好的事情是设置相对于可执行文件的库位置,在这种情况下是 /usr/lib/jvm/.../java。
  4. 静态链接每个库及其依赖项。我担心这会导致 libPlugin2 的两个副本(一个动态副本和一个静态副本)在过去给我们带来了各种各样的问题。

在 Windows 上,在加载插件之前调用 SetDllDirectory 可以很好地解决这个问题。有没有我忽略/误解的解决方案?我这样做是不是完全错误的方式?

【问题讨论】:

    标签: java c++ linux shared-libraries


    【解决方案1】:

    您可以在 Java 进程本身中设置 LD_LIBRARY_PATH 环境变量。

    【讨论】:

    • 啊,谢谢,我也有同样的想法,但是当你第一次运行应用程序时,Linux 会缓存 LD_LIBRARY_PATH —— 它不能在运行时修改。 stackoverflow.com/questions/856116/…
    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 2012-11-25
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 2013-01-01
    相关资源
    最近更新 更多