【问题标题】:JavaCPP, UnsatisfiedLinkError when native library is archived in JARJavaCPP,在 JAR 中归档本机库时出现 UnsatisfiedLinkError
【发布时间】:2016-04-30 22:39:01
【问题描述】:

我正在尝试从 Java 调用 Haskell 代码,使用 JavaCPP 来帮助创建必要的 JNI 绑定,正如 this question 中已经讨论的那样。

这就是我的使用方式:

<rootdir>
  /javacpp.jar
  /build (destination of libraris)
  /src   (contains Haskell code)
  /com/example/HSCode.java (Java class to load and use native lib)

HScode.java的内容:

package com.example;

import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;

@Platform(include={"<HsFFI.h>","HScode_stub.h"})
public class HScode {
    static { Loader.load(); }
    public static native void hs_init(int[] argc, @Cast("char***") @ByPtrPtr PointerPointer argv);
    public static native String code_hs(String text);

    public static void main(String[] args) throws FileNotFoundException {
        String s = new Scanner(new File("test.txt")).useDelimiter("\\Z").next();
        hs_init(null, null);
        String s1 = code_hs(s);
        System.out.println(s1);
    }
}

编译:

cd <rootdir>
ghc --make -isrc -dynamic -shared -fPIC src/HScode.hs \
     -o build/libHScode.so -lHSrts-ghc7.8.4 -optl-Wl,-rpath,.
javac -cp javacpp.jar com/example/HScode.java
java -jar javacpp.jar -d build \
     -Dplatform.compiler=ghc -Dplatform.includepath="src:com/example" \
     -Dplatform.compiler.output="-optl-Wl,-rpath,. -optc-O3 -Wall build/libHScode.so -dynamic -fPIC -shared -lstdc++ -lHSrts-ghc7.8.4 -o " com.example.HScode

按照这种方法,我可以使用javacpp 创建一个libHScode.so 和一个libjniHScode.so,它们运行良好:

$ java -cp javacpp.jar:. com.example.HScode

罐子

现在,接下来的步骤是我想将所有内容打包到一个 jar 中,并且能够从一个更大的 java 项目中使用这个 jar 的 com.example.HScode

JavaCPP 的页面提及:

[...] 此外,在运行时,Loader.load() 方法会自动 从 Java 资源中加载本地库,这些资源位于 正确的目录由构建过程。 它们甚至可以存档 在 JAR 文件中,它不会改变任何内容。用户根本不需要图 了解如何让系统加载文件。

所以我认为这应该可行。

但是,如果我从上面的 build 文件夹的内容中创建一个 jar HScode.jar,以便我的 jar 同时包含 libjniHScode.solibHScode.so,然后运行它:

$ java -cp javacpp.jar:HScode.jar:. com.example.HScode

然后它找不到我的本机代码(为匿名而编辑的异常):

Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniHScode in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1865)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:597)
    at org.bytedeco.javacpp.Loader.load(Loader.java:438)
    at org.bytedeco.javacpp.Loader.load(Loader.java:381)
    at com.example.HScode.<clinit>(HScode.java:13)
Caused by: java.lang.UnsatisfiedLinkError: /compilation-path/linux-x86_64/libjniHScode.so: HScode.so: cannot open shared object file: No such file or directory
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1937)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1822)
    at java.lang.Runtime.load0(Runtime.java:809)
    at java.lang.System.load(System.java:1086)
    at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:580)

我错过了什么?有谁知道 JavaCPP 在 jar 中存档时是否真的可以找到本机代码?

【问题讨论】:

    标签: jar java-native-interface shared-libraries javacpp


    【解决方案1】:

    通过调用javacpp -jar javacpp.jar com.example.HScode 为本地库构建,自动将它们输出到com/example/linux-x86_64/Loader 从那里加载它们。因此,当通过其他方式构建原生库时,如果我们希望 Loader 找到它们,无论是在 JAR 文件内部还是作为普通文件,它们仍然需要移动到 com/example/linux-x86_64/

    【讨论】:

    • 谢谢,我想在您的回复中,我正在编辑我的问题以删除不必要的内容并包含有关编译的详细信息。我使用-d build 将创建的库移动到“干净”文件夹中这一事实是否有问题?
    • @cornuz 你可以使用Loader.load(URL[] urls, String libnameversion) 和来自ClassLoader.getResource()URL,如果你想要的话。
    • 您关于在 jar 中保持相同结构的评论完全有道理。我想尝试使用标准的加载器。现在 jar 包含com/example/linux-x86_64/libjniHScode.so。我仍然不知道将原生库 libHScode.so 放在罐子内的哪个位置。我在com/example/linux-x86_64/ 和根目录中都试过了。没有运气。但它确实在本地库位于 jar 之外时起作用,我在其中调用 java -cp javacpp.jar:HScode.jar:. com.example.HScode
    • @cornuz 要被提取,它需要成为@Platform 注释的一部分,或者link="HScode"preload="HScode"
    • 确实,link 注释使它工作,谢谢!我假设它等同于使用-Dplatform.link="HScode"。仅使用后者可以使-copylibs 选项起作用,但不会使 lib 在运行时从 jar 中提取。
    猜你喜欢
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多