jna.loadLibrary 找不到本机库文件

jna.loadLibrary cannot find native library file

我已经用本机库包装器创建了自己的 jar。生成的 jar 的结构是:

library.jar
 |- com (there are my .java classes)
 |- libs (there is the native - libmylib.so)
 |- META-INF

我加载本机库如下:

MyLibClass instance = (MyLibClass) Native.loadLibrary("mylib", MyLibClass.class);

现在想把这个库添加到其他项目中使用。但是当我创建 MyLibClass 的实例时,我收到一个错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'mylib':
libmylib.so: cannot open shared object file: No such file or directory

我该如何解决这个问题?

JNA Getting Started 页面所述,

使您的目标库可供您的 Java 程序使用。有几种方法可以做到这一点:

  • 首选方法是将 jna.library.path 系统 属性 设置为目标库的路径。 属性 类似于java.library.path,但仅适用于 JNA 加载的库。
  • 在启动 VM 之前更改适当的库访问环境变量。这是 Windows 上的 PATH、Linux 上的 LD_LIBRARY_PATH 和 OSX 上的 DYLD_LIBRARY_PATH
  • 在路径 {OS}-{ARCH}/{LIBRARY} 下的类路径中提供本机库,其中 {OS}-{ARCH} 是 JNA 的本机库规范前缀(例如 win32-x86linux-amd64、或 darwin)。如果资源在 jar 文件中,它将在加载时自动提取。

我使用静态加载程序 class 完成了如下操作:

static class Loader {

    private Loader() {
    }

    static String getNative() {
        InputStream in = null;
        FileOutputStream fos = null;
        File fileOut = null;
        System.setProperty("jna.library.path",
                System.getProperty("java.io.tmpdir"));

        in = Loader.class.getResourceAsStream(
                        "/libs/libmylib.so");

        if (in != null) {
            try {
                fileOut = File.createTempFile("mylib", ".so");
                fileOut.deleteOnExit();

                fos = new FileOutputStream(fileOut);

                int count;
                byte[] buf = new byte[1024];

                while ((count = in.read(buf, 0, buf.length)) > 0) {
                    fos.write(buf, 0, count);
                }

            } catch (IOException ex) {
                throw new Error("Failed to create temporary file: " + ex);
            } finally {
                try {
                    in.close();
                } catch (IOException ex) {
                }

                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException ex) {
                    }
                }

                return fileOut.getAbsolutePath();
            }
        } else {
            throw new Error("Couldn't open native library file");
        }
    }
}

我从资源中加载库文件并将其内容复制到临时目录。正如您在执行此操作之前看到的那样,我将 jna.library.path 设置为临时文件夹,因此 JNA 将在那里搜索库。

此外,我正在这样加载库:

MyLibClass instance = (MyLibClass) Native.loadLibrary(Loader.getNative(), MyLibClass.class);