Spring Boot 2.X 加载 so 库

举报
福州司马懿 发表于 2021/11/19 04:27:10 2021/11/19
【摘要】 新建临时目录 首先通过 System.getProperty 获取系统环境变量 System.getProperty("java.io.tmpdir") 在 windows 上,C:\Users\用...

新建临时目录

首先通过 System.getProperty 获取系统环境变量

System.getProperty("java.io.tmpdir")

  • 在 windows 上,C:\Users\用户名\AppData\Local\Temp\
  • 在 Linux 上,/tmp/

需要在该目录下,新建一个项目文件夹,用来存放当前项目的文件。

下面以 bsdiff 服务器,加载 so 为例(与 File.separator 是与系统相关的环境分隔符 )

public static final String TMP_DIR = System.getProperty("java.io.tmpdir") + "BsDiff" + File.separator;

放置资源文件

首先在 src\main\resources 目录下,新建一个 lib 目录,然后在该目录下,贴入 so 库。
在这里插入图片描述

读取资源文件

  1. Class.getResourceAsStream(String path)
  • path不以“/”开头时,默认是从当前类所在的包下面获取资源
  • path以“/”开头时,则是从项目的classPath根下获取资源
  1. ClassLoader.getResourceAsStream(String path)
    默认是从classpath根下获取,path不能以“/”开头,path是指类加载器的加载范围,在资源加载的过程中,使用逐级向上的委托的形式加载的,“/”表示Boot ClassLoader中的加载范围,因为这个类加载器是C++实现的,所以加载范围为null。

  2. ServletContext.getResourceAsStream(String path)
    默认从WebAPP根目录下取资源,Tomcat下path是否以“/”开头无所谓,当然这和具体的容器实现有关。

创建一个 LibLoader 类。

/**
 * 将resources目录下的文件,写入到File中
 */
private static boolean saveResource(String resourcePath, File dstFile) {
	InputStream in = null;
	FileOutputStream fos = null;
	try {
		in = LibLoader.class.getResourceAsStream(resourcePath);
		System.out.println("in = " + in);
		if(in != null) {
			fos = new FileOutputStream(dstFile);
			int BUFF_SIZE = 1024, len;
			byte[] buffer = new byte[BUFF_SIZE];
			while((len = in.read(buffer)) != -1) {
				fos.write(buffer, 0, len);
			}
			return true;
		}
	} catch(Exception e) {
		e.printStackTrace();
	} finally {
		if(fos != null) {
			try {
				fos.flush();
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if(in != null) {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	return false;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

调用函数

注意:由于资源文件在 resources 目录下,所以 getResourceAsStream 的参数要以 “/” 打头。

下面这段代码,先判断缓存目录下是否有该so文件,如果有,则使用 System.load 加载该库;否则

public static void loadLib(String libName) {
	String folderName = System.getProperty("java.io.tmpdir") + "BSDiff" + File.separator + "lib" + File.separator;
	File folder = new File(folderName);
	folder.mkdirs();
	File libFile = new File(folder, libName);
	String path = libFile.getAbsolutePath();
	//如果文件不存在,或者文件长度为0,则从资源路径中复制文件到临时文件夹
	if(libFile.exists() && libFile.length() > 0) {
		System.load(path);
	} else {
		String resourcePath = "/lib/" + libName;
		System.out.println(resourcePath);
		boolean result = saveResource(resourcePath, libFile);
		if(result) {
			System.load(path);
		} else {
			System.out.println("save resource to tmp dir fail!");
		}
	}	
}	

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

加载 so 库

最后声明含有本地方法的类,然后实例化并调用即可。
注意:如果只是声明,却没有被实例化,static 方法块内的代码是不会被执行的。

public class DiffPatchUtil {

    static {
        //System.loadLibrary("diff-patch");
    	LibLoader.loadLib("diff-patch.so");
    }

    /**
     * 比较路径为oldPath的文件和newPath的文件之间差异,并生成patch包,存储于patchPath
     *
     * @param oldPath   示例:/sdcard/old.apk
     * @param newPath   示例:/sdcard/new.apk
     * @param patchPath 示例:/sdcard/diff.patch
     */
    public static native int diff(String oldPath, String newPath, String patchPath);

    /**
     * 使用路径为oldPath的文件与路径为pathPath的补丁包,合成新的文件,并存储于newPath
     *
     * @param oldPath   示例:/sdcard/old.apk
     * @param newPath   示例:/sdcard/new.apk
     * @param patchPath 示例:/sdcard/patch.patch
     */
    public static native int patch(String oldPath, String newPath, String patchPath);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

文章来源: blog.csdn.net,作者:福州-司马懿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/chy555chy/article/details/98478703

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。