正常情況下, 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); } } }