打包so 库及从jar 中加载

一. 目的

主要场景就是,编写一个三方库,这个三方库使用到了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 库依赖了其他的库,那么需要先加载依赖的库

你可能感兴趣的:(打包so 库及从jar 中加载)