java加載jar包中的庫資源

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

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章