2010-01-10 63 views
11

SWT帶有基礎JAR和每個平臺(Windows,Linux/32位,Linux/64bit,Mac,AIX等)的特定JAR。我如何創建一個可執行的JAR來在運行時選擇正確的平臺JAR?如何使用在所有平臺上運行的SWT創建可執行JAR?

[編輯]我正在考慮提供一個子目錄中的所有平臺JAR,然後main()將修改類加載器。有沒有人已經試過這個?

+1

你爲什麼不爲每個平臺(一拉的Eclipse)發佈幾個可執行文件? – 2010-01-10 23:30:49

+0

因爲SWT只佔用應用程序的一小部分:整個事情目前爲30MB。因此,我可以要求人們爲每個平臺下載32MB或下載到處運行的單個40MB(用於六個平臺)文件。 – 2010-01-11 08:16:06

+0

在eclipse的情況下,我們有10次以上的下載,每次> 100MB,它們之間的唯一區別是SWT jar。我想要一次下載或一次大的主要下載和每個平臺的小型下載,當我第一次運行應用程序時會自動下載。 – 2010-01-11 08:29:34

回答

1

IIUC,你仍然必須指定特定於平臺的JNI庫的問題。你可能可以利用Java Web Start這個,但我沒有嘗試過。或者,某些項目爲受支持的平臺構建自定義安裝程序。例如,Deploying SWT Applications on Mac OS X描述瞭如何構建SWT Mac應用程序包。該方法用於此example。我也看到了這個JarBundler Ant Task使用。

附錄:文章Deploying an SWT application on Java Webstart包括一些有用的參考文獻。

+0

我現在已經嘗試使用URLClassLoader,但存在兩個問題:如果JAR不在MANIFEST.MF中的ClassPath中,則加載DLL將失敗。這意味着我必須同時將* all * SWT JAR添加到類路徑中。這導致了32位和64位DLL可見並且任一方的加載都會失敗的問題。 *嘆*最後,我會將所有JAR添加到類路徑中,但只將一個SWT JAR複製到lib目錄中。這樣,只會加載一個JAR。 – 2010-01-10 22:22:17

+0

我可以看到技術吸引力,但我也可以看到維護困難。面對類似的問題,我添加了提到JWS的SO文章的鏈接。 – trashgod 2010-01-10 23:18:52

0

對於不同的平臺使用不同的shell腳本並在腳本中指定平臺特定的jar會更容易。

+0

我可以編寫shell腳本,但我真的希望避免這種情況。我當前的解決方案(將所有SWT JAR添加到類路徑中,但只將正確的一個複製到lib目錄中)。現在,我只需要編寫一個安裝程序:) – 2010-01-10 22:23:23

5

對於我目前的工作,我需要提供一個可執行的jar文件,它可以在自己內部加載jar並執行第二個main()。基本上是一個引導main()和一個應用程序main()。

步驟1在清單「主級」你把你的引導類

第2步:當你的引導類運行時,它不能解壓縮是自己的罐子,它裏面的所有jar文件到一個臨時目錄。使用類似下面的行來獲得你自己的jar。

Main.class.getProtectionDomain().getCodeSource().getLocation().toURI() 

第3步:您引導類通過「os.name」屬性檢測OS並加載從臨時目錄中的正確的jar這個

private static void loadJarIntoClassloader(URL u) throws Exception 
{ 
    URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); 

    Class<URLClassLoader> sysclass = URLClassLoader.class; 
    Method method = sysclass.getDeclaredMethod("addURL", URL.class); 
    method.setAccessible(true); 
    method.invoke(sysLoader, new Object[]{u}); 
} 

第4步:現在你應該可以通過調用應用程序main()來運行你的應用程序。

注意:這個小黑客依賴於你的JVM,使用URLClassLoader作爲它的SystemClassLoader,這對於Sun JVMs來說是正確的,而對其他的JVM則不是這樣。

這樣你就可以只提供一個罐子,它將自行解開包裝並運行正確的罐子。

+1

如果您想獨立於類加載器的類型,只需使用工廠'newInstance(urls,parentClassLoader)'方法來包裝它,然後使用'Thread加載新的類加載器.currentThread()。setContextClassLoader()'。 – 2010-01-11 08:19:20

+0

+1有趣的想法創建一個主類路徑,然後調用另一個。 – 2010-01-11 08:20:20

+0

@Aaron感謝您的提示,我將不得不嘗試 – karoberts 2010-01-11 18:23:12

相關問題