Java導出成可運行Jar包 dll或者so加載失敗的解決方案


正常情況下, xxx.class.getResourceAsStream(lib) 這樣就可以獲取到了。但是我的是在JFrame的初始化中的, 所以需要Thread.currentThread().getContextClassLoader().getResourceAsStream(lib); 這樣來獲取。   這個坑  找了蠻久才找到解決方案記錄下。

嗯   看了一些解決方案,1、把庫跟jar包一起拷貝打包 2、放入指定路徑 添加環境變量 通過環境變量來獲取庫路徑等等 終究還是比較麻煩的。  

經過測試發現  本文的方案 還是沒有最終解決這個問題   手里還有別的事  先放下了后面再研究

private synchronized static void copyLib(String libFullName, String arch_libfile_suffix) throws IOException {
    InputStream in = null;   
    BufferedInputStream reader = null;   
    FileOutputStream writer = null;   
    File f = new File(".");
    
    String libs[] = { libFullName, libFullName.replace(arch_libfile_suffix, ".c"), libFullName.replace(arch_libfile_suffix, ".h") }; 
    for(int i = 0;i<libs.length;++i){
        File extractedLibFile = new File(f + File.separator + libs[i]);   
        if(!extractedLibFile.exists()){   
            //打包進jar中后, 可以用zip軟件打開jar文件 看看你需要調用的dll或者so 在jar中的路徑就是這個lib的值       
            String lib = libs[i].replace("lib" + File.separatorChar, "");
//          String lib = libs[i];
            System.out.println("lib = " + lib);
            try {
                // “/”代表Jar包的根目錄
                in = Thread.currentThread().getContextClassLoader().getResourceAsStream(lib);
                //   踩過的坑  這些方式都沒能夠成功獲取到。   這是因為我的獲取是在UI線程中的。
                //   MD5.class.getResourceAsStream("/" + libs[i]);
                //   MD5.class.getClassLoader().getResourceAsStream("/" + libs[i]);
                //   MD5.class.getResource(libFullName);
                System.out.println(" getResourceAsStream == " +  lib);
               
                reader = new BufferedInputStream(in);
                writer = new FileOutputStream(extractedLibFile);
 
                byte[] buffer = new byte[1024];         
                while (reader.read(buffer) > 0){
                    writer.write(buffer);
                    buffer = new byte[1024];
                }
            } catch (IOException e){
                e.printStackTrace();
            } finally {
                if(in!=null)
                    in.close();
                if(writer!=null)
                    writer.close();
            }
        }   
    }   
}

這種方案  經過測試在mac上面是可行的   但是在windows上面 總是拷貝lib失敗  報 IOException 異常. 先記錄 后面再解決

 

 

 還有下面這種解決方案,來自https://www.cnblogs.com/FlyingPuPu/p/7598098.html

 就是把Jar 當作zip文件遍歷,找出需要加載的lib 然后拷貝到指定路徑再進行加載

/**
 * 加載項目下的native文件,DLL或SO
 *
 * @param dirPath 需要掃描的文件路徑,項目下的相對路徑
 * @throws IOException
 * @throws ClassNotFoundException
 */
public synchronized static void loader(String dirPath) throws IOException, ClassNotFoundException {
    Enumeration<URL> dir = Thread.currentThread().getContextClassLoader().getResources(dirPath);
    // 獲取操作系統類型
    String systemType = System.getProperty("os.name");
    String systemArch = System.getProperty("os.arch");
    // 獲取動態鏈接庫后綴名
    String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so";
    while (dir.hasMoreElements()) {
        URL url = dir.nextElement();
        String protocol = url.getProtocol();
        if ("jar".equals(protocol)) {
            JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
            JarFile jarFile = jarURLConnection.getJarFile();
            // 遍歷Jar包
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry jarEntry = entries.nextElement();
                String entityName = jarEntry.getName();
                if (jarEntry.isDirectory() || !entityName.startsWith(dirPath)) {
                    continue;
                }
                if (entityName.endsWith(ext)) {
                    loadJarNative(jarEntry);
                }
            }
        } else if ("file".equals(protocol)) {
            File file = new File(url.getPath());
            loadFileNative(file, ext);
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM