1、加载jar包中资源
加载文件方法有很多,不过如果文件打包在jar包内如何进行加载呢?
路径可以很轻易的获取,不过jar包是一个文件,而非一个文件夹,jar包中的资源并未解压到外部环境中,因而我们无法通过常用的加载文件的方法获知jar包中文件。通常通过如下接口来读取jar包中文件:
InputStream in = this.getClass().getResourceAsStream("/lib/libexample.so");
这里路径是jar包中路径。
getResourceAsStream函数体如下,返回了jar包内文件的输入流
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
主要利用了ClassLoader类。
每个类都有自定义的ClassLoader对象,并通过这个ClassLoader对象对类进行加载。
当JVM需要某类时,它根据名称向ClassLoader要求这个类,然后由ClassLoader返回这个类的class对象。ClassLoader负责载入系统的所有Resources(Class,文件,来自网络的字节流等),通过ClassLoader从而将资源载入JVM。
2、加载库文件
常用的加载库文件(不论是JNI库文件还是非JNI库文件)的方法包括如下两种
- System.load 参数为库文件的绝对路径,可以是任意路径。
例如:
System.load("C://Documents and Settings//TestJNI.dll");。
- System.loadLibrary 参数为库文件名,不包含库文件的扩展名。
例如:
System. loadLibrary ("TestJNI");
3、code
如果需要加载jar包中.so文件,需要上面两个接口配合。基本思想是通过getResourceAsStream()读取jar包中资源的文件流,并将之存入临时文件,再通过System.load加载。
public static void load(String path) throws IOException {
if(!path.startsWith("/")){
throw new IllegalArgumentException("Wrong path :" + path);
}
//如果存在本文件,直接加载,并返回
File inputFile = new File(path);
if(inputFile.exists() && inputFile.isFile()){
System.load(path);
return;
}
String fileName = path.substring(path.lastIndexOf('/')+1);
if(fileName == null || fileName.isEmpty()){
throw new IllegalArgumentException("The fileName should not be null");
}
String prefix = fileName.substring(0, fileName.lastIndexOf(".")-1);
String suffix = fileName.substring(fileName.lastIndexOf("."));
//创建临时文件,注意删除
File tmp = File.createTempFile(prefix, suffix);
tmp.deleteOnExit();
System.out.println(tmp.getAbsolutePath());
byte[] buff = new byte[1024];
int len;
OutputStream out = new FileOutputStream(tmp);
//从jar中读取文件流
InputStream in = MyFileLoad.class.getResourceAsStream(path);
try{
while((len = in.read(buff)) != -1){
out.write(buff, 0, len);
}
}finally {
in.close();
out.close();
}
//加载库文件
System.load(tmp.getAbsolutePath());
}