2009-10-23 83 views
59

我買了第三方Java庫,其中包含一個JAR文件和兩個DLL文件。我編寫了自己的調用第三方JAR文件的Java程序。現在我的問題是如何將所有代碼打包到一個包含我所有代碼和第三方JAR和DLL的JAR文件中?如何製作包含DLL文件的JAR文件?

我知道SWT就是這樣的情況。 swt.jar包含dll文件,但我不知道如何做到這一點以及如何使其正常工作。

回答

68

只是在罐子的任何位置將其打包。有一件事你必須記住 - 雖然在你使用DLL之前,你需要從JAR中提取這些文件並將它們轉儲到硬盤上,否則你將無法加載這些文件。所以基本上 - 我爲客戶做了JNI項目,我將在戰爭中使用這種jar包。但是 - 在運行任何本地方法之前,我會將DLL作爲資源並將其寫入臨時目錄中的光盤。然後,我會跑在我的DLL被設置在同一位置我剛寫的DLL

哦,以防萬一常規初始化代碼:沒有什麼特別的包裝DLL或任何其他文件放入罐子。這就像包裝的東西到拉鍊

下面是一些代碼,我只是挖了

public class Foo { 
private static final String LIB_BIN = "/lib-bin/"; 
private final static Log logger = LogFactory.getLog(ACWrapper.class); 
private final static String ACWRAPPER = "acwrapper"; 
private final static String AAMAPI = "aamapi51"; 
private final static String LIBEAU = "libeay32"; 

static { 
    logger.info("Loading DLL"); 
    try { 
     System.loadLibrary(ACWRAPPER); 
     logger.info("DLL is loaded from memory"); 
    } catch (UnsatisfiedLinkError e) { 
     loadFromJar(); 
    } 
} 

/** 
* When packaged into JAR extracts DLLs, places these into 
*/ 
private static void loadFromJar() { 
    // we need to put both DLLs to temp dir 
    String path = "AC_" + new Date().getTime(); 
    loadLib(path, ACWRAPPER); 
    loadLib(path, AAMAPI); 
    loadLib(path, LIBEAU); 
} 

/** 
* Puts library to temp dir and loads to memory 
*/ 
private static void loadLib(String path, String name) { 
    name = name + ".dll"; 
    try { 
     // have to use a stream 
     InputStream in = ACWrapper.class.getResourceAsStream(LIB_BIN + name); 
     // always write to different location 
     File fileOut = new File(System.getProperty("java.io.tmpdir") + "/" + path + LIB_BIN + name); 
     logger.info("Writing dll to: " + fileOut.getAbsolutePath()); 
     OutputStream out = FileUtils.openOutputStream(fileOut); 
     IOUtils.copy(in, out); 
     in.close(); 
     out.close(); 
     System.load(fileOut.toString()); 
    } catch (Exception e) { 
     throw new ACCoreException("Failed to load required DLL", e); 
    } 
} 
    // blah-blah - more stuff 
} 
+7

謹慎對這種方法的一個詞 - 確保你清理臨時文件。如果每次重新使用相同的路徑,請考慮如果多個應用程序使用您的JAR會發生什麼情況(如果另一個應用程序已對臨時文件鎖定,則會發生什麼情況)。只要小心 - 有時分開部署JAR和DLL會更容易。 – 2009-10-24 05:50:57

+0

可以更改代碼以覆蓋以前安裝的文件。在我的情況 - 這是一個網絡應用程序,它不會被頻繁回收,BU確實是 - 如果你只是將代碼複製「原樣」你會得到的DLL的新副本每次執行它 – Bostone 2009-10-24 06:03:06

+7

有一點要記住:我正在使用依賴於其他DLL的JNI DLL。我將所有DLL包含在一個jar中,並使用上面的代碼解壓縮。但是我得到java.lang.UnsatisfiedLinkError異常說「無法找到依賴庫」。問題是您必須依次調用DLL上的System.load(),以便首先加載依賴的DLL。 – 2010-05-24 21:27:20

6

使用http://www.jdotsoft.com/JarClassLoader.php其中可以加載DLL和JAR文件從無限嵌套另一個JAR。例如,DLL可能位於另一個根JAR中的JAR中。所有DLL和JAR都像在類路徑或庫路徑中一樣加載。

+23

他人注意事項:許可證是GPLv3,這大大限制了適用性。 – 2011-11-03 19:24:21

+4

另請注意:這個類加載器將所有嵌套的jar包解包到一個臨時目錄中。所以它就像第一個答案。本地庫僅在需要時解壓縮。 – drzymala 2013-02-14 17:15:30

+1

提供商業許可證。 – drzymala 2013-02-14 17:25:05