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());
}