一. 目的
主要场景就是,编写一个三方库,这个三方库使用到了native 库,然后要把三方库打包成jar 包,同时三方库还要能加载被打包进的native 库。
二. 操作
环境:
-
系统:Mac
-
IDE:idea
-
构建:maven
1. 打包
native 库,这里是一个 .so 文件,已经提前生成好了,为了能在执行 mvn deploy 时,将so 文件打进 jar 包,需要将so 文件放入resources 文件夹下,
image.png
这里,为了加载时方便,在resources 目录下,创建一个和需要加载so 库的Java 类 相同的文件夹路径,
image.png
这样,在打包后,so 文件就会和 上图中加载so 库的DataOperate 类处于同一目录。
2. 加载
经过上面的步骤,so 文件就会被打包到jar 中,在使用时,用原来直接加载文件路径(System.load())的方式,就会提示找不到这个库,因为这个库是在jar 中的,已经不是一个独立的文件了,所以要想加载这个so 就需要把so 从jar 中提取出来,保存为临时文件,然后再加载。
代码如下:
private static void loadLib(String path, String name) { // path 是自定义路径,name 是so 文件名
try {
// 取出so 库文件流,getResourceAsStream 这个方法,会在DataOperate 这个类的路径基础上去找文件,
// 这就是为什么在打包时把 so 文件和要加载的类放在同一路径的原因,加载比较方便。
InputStream in = DataOperate.class.getResourceAsStream(name);
String tmpPath = System.getProperty("java.io.tmpdir") + "/" + path; // 临时文件路径
// 创建新文件
File fileOutDic = new File(tmpPath);
if (!fileOutDic.exists()) {
fileOutDic.mkdirs();
}
File fileOut = new File(tmpPath + name);
if (!fileOut.exists()) {
fileOut.createNewFile();
}
OutputStream out = new FileOutputStream(fileOut);
IOUtils.copy(in, out, 8024);
in.close();
out.close();
System.load(fileOut.getAbsolutePath()); // 调用load 方法加载
} catch (Exception e) {
throw new RuntimeException("加载so 库失败!", e);
}
}
使用这种方法加载so 库,需要注意一些事项:
-
1)注意临时文件的清理,如果需要重用临时文件的话,注意如果有多个应用在使用这个jar 包,可能会因为这个临时文件被加锁,导致另外的程序产生错误
-
2)如果这个so 库依赖了其他的库,那么需要先加载依赖的库
网友评论