【问题标题】:Dynamically load native library动态加载原生库
【发布时间】:2018-01-24 13:27:48
【问题描述】:

我需要一种方法来在 jar 文件中加载库而不提取它。有没有办法可以使用 getClass().getResourceAsStream("xxx") 之类的方法

结构如下:

myjar.jar
 - lib/
   - <somelib>.<libext>
 - <package>
   - Foo.class

Foo.class 将是加载并连接到本机库的类,如果 lib 文件夹位于 &lt;package&gt; 内,方法也应该可以工作

【问题讨论】:

    标签: java java-native-interface static-libraries dynamic-class-loaders


    【解决方案1】:

    不,如果不先解压缩,就无法从 jar 文件中加载库,您需要至少将库解压缩到 tmp 文件夹中才能加载它使用例如:

    System.load("path/to/libAbc.so")

    目前无法在 java 中从内存或 zip 文件加载库。加载库的方法是native void ClassLoader.NativeLibrary.load(String name),库的name也被java.lang.ClassLoader内部使用来跟踪加载的库,所以目前你不能使用与真实文件不同的任何东西加载为本机库,因为它不适合当前机制。

    由于本地库的加载是在本地代码的帮助下完成的,答案取决于是否有办法在 C 代码中加载本地库:dlopen from memory?

    理论上可以做到,但是因为它是特定于平台的,并且有许多需要考虑和解决的方面,所以它不是用 Java 实现的,也不是标准和/或在 C 语言中也很容易。

    目前在java中,没有办法做到这一点,如果有人会创建这样一个可以做到这一点的本机库,这可能会改变,但现在我不知道任何这样的库。

    【讨论】:

    • 不应该这样,因为它可以读取 jar 中的任何文件,并且 lib 仍然是一个文件,并且 System.LoadLibrary() 仍然会读取路径中的文件。那么不应该有办法直接将全部内容发送到内存中并从内存中读取吗??
    • @Android_Dev 不应该这样,因为它可以读取 jar 中的任何文件,并且 lib 仍然是一个文件,并且 System.LoadLibrary() 仍然会读取路径中的文件。那么不应该有办法直接将全部内容发送到内存中并从内存中读取吗? 你为什么会这么认为?加载本机库由操作系统完成,而不是 JVM。
    • @AndrewHenle 是的,我知道它必须由操作系统加载,但是操作系统不关心代码的物理位置,代码的指针和寄存器存储在内存中,所以如果我可以将所有内容直接发送到这一点,它将正常执行(我假设)。
    • 查看源代码 java 存储指向函数的指针并使用它来执行本机任务。 NativeLibrary#find(String)。所以可能有某种方式。
    【解决方案2】:

    sci-java 本地库加载器也处理这个(尽管它在幕后提取它)。 您可能想尝试一下:https://mvnrepository.com/artifact/org.scijava/native-lib-loader

    【讨论】:

      【解决方案3】:

      如果不把它放在某个地方(至少是某个临时位置),你就无法做到。

      你可以看这里:

      https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031

      这个秘籍为您提供了一个模板,该模板将从 jar 中获取您的本机库,将其提取并加载到您的 Java 代码中。

      享受 JNI 的乐趣!

      【讨论】:

        猜你喜欢
        • 2014-06-03
        • 2011-09-06
        • 1970-01-01
        • 1970-01-01
        • 2018-03-17
        • 2020-06-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多