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-x86
、linux-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);
我已经用本机库包装器创建了自己的 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-x86
、linux-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);