载入库文件有两个函数,System.load 和 System.loadLibrary。
当使用System.load时,需要输入文件的全路径,例如:System.load(“/tmp/test.so”);
当使用System.loadlibrary时是在系统的library 的目录中需找复合条件的库文件,可以使用-Djava.library.path=[path]参数,来指定Java程序加载库文件的路径,或者将库文件(*.so,*.dll)复制到include的默认路径,Linux一般是/usr/lib目录下,当然你可以编辑/etc/ld.so.conf.d/下的文件,设定自己的库查找路径ldconfig -v|grep xxx看看有没有你的动态库。
注意:
linux中 文件名是libname.so 调用只能是System.loadLibray(name) 函数会自动加上lib的前缀,不能带后缀so 不能带路径,默认在 java.library.path路径中查找,可以用System.getProperty(“java.library.path”) 查看, 然后将 so文件拷贝到库目录 例如 /usr/lib /usr/lib64 等
而windows中可以带路径例如 文件名是name.dll 调用可以是 System.loadLibray(D:\\name)
备注走过的坑:
测试环境 centos7.x 64位
把so文件打入jar包中,尝试jar包内相对路径调用,失败(貌似不可行)
网上查询思路:将jar包中的动态库文件,以流的方式读到jar包以外的临时目录tmp,然后利用Sytem.load 以绝对路径加载
应该是可行的,但是本人加载库文件成功,调用函数失败,提示java.lang.UnsatisfiedLinkError 原因未知,不深究(本人在linux下带绝对路径都没成功过)
static {
try {
Class c = LinuxTest2.class;
URL location = c.getProtectionDomain().getCodeSource().getLocation();
ZipFile zf = new ZipFile(location.getPath());
InputStream in = zf.getInputStream(zf.getEntry("lib/libWSR.so"));
File f = File.createTempFile("JNI-", "Temp");
FileOutputStream out = new FileOutputStream(f);
byte [] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.close();
String fpath = f.getAbsolutePath();
System.out.println("fpath:" + fpath);
System.load(f.getAbsolutePath());
f.delete();
} catch (Exception e) {
e.printStackTrace();
}
java 和动态库 函数参数对应表:
另外: 动态库函数 参数传递返回值问题 例如 DWORD* 在java中对应什么类型?
动态库中头文件函数声明: int (*ws_getCardNo)(char*,DWORD *);
char* 类型在java中可以用 String类型来替换
DWORD* 是指针类型 java 对应的 int类型的指针 但是int是基础类型 如果需要参数返回值的话 可以用 int数组来实现,数组长度为1:
int[] b = new int[1]
java中对应的 函数声明 :public native static int ws_getCardNo(String p, int[] b);
相关:
http://www.cnblogs.com/LiuYanYGZ/p/6109516.html
https://github.com/java-native-access/jna/blob/master/www/Mappings.md