我有一個工作實現,現在引用SWT FAQ。
這種方法是現在作爲一個Ant任務使用:SWTJar
[編輯] SWTJar現在已經更新爲使用阿列克謝·羅曼諾夫的解決方案,如上所述。
build.xml
首先,我建立一個包含所有我的應用程序類的罐子。
<!-- UI (Stage 1) -->
<jarjar jarfile="./build/tmp/intrace-ui-wrapper.jar">
<fileset dir="./build/classes" includes="**/shared/*.class" />
<fileset dir="./build/classes" includes="**/client/gui/**/*.class" />
<zipfileset excludes="META-INF/*.MF" src="lib/miglayout-3.7.3.1-swt.jar"/>
</jarjar>
接下來,我建立一個罐子來包含所有的以下內容:
- JAR文件
- 罐子類
- 的 「瓶 - 在-JAR」 類裝載器類
- 一個特殊loader類 - 見下文
下面是從build.xml中的片段。
<!-- UI (Stage 2) -->
<jarjar jarfile="./build/jars/intrace-ui.jar">
<manifest>
<attribute name="Main-Class" value="org.intrace.client.loader.TraceClientLoader" />
<attribute name="Class-Path" value="." />
</manifest>
<fileset dir="./build/classes" includes="**/client/loader/*.class" />
<fileset dir="./build/tmp" includes="intrace-ui-wrapper.jar" />
<fileset dir="./lib" includes="swt-*.jar" />
<zipfileset excludes="META-INF/*.MF" src="lib/jar-in-jar-loader.jar"/>
</jarjar>
TraceClientLoader.java
這個加載類使用的jar-在-JAR加載器來創建它從兩個罐子加載類一個ClassLoader。
一旦我們有了這個類加載器,我們可以使用反射推出實際的應用主要方法。
public class TraceClientLoader
{
public static void main(String[] args) throws Throwable
{
ClassLoader cl = getSWTClassloader();
Thread.currentThread().setContextClassLoader(cl);
try
{
try
{
System.err.println("Launching InTrace UI ...");
Class<?> c = Class.forName("org.intrace.client.gui.TraceClient", true, cl);
Method main = c.getMethod("main", new Class[]{args.getClass()});
main.invoke((Object)null, new Object[]{args});
}
catch (InvocationTargetException ex)
{
if (ex.getCause() instanceof UnsatisfiedLinkError)
{
System.err.println("Launch failed: (UnsatisfiedLinkError)");
String arch = getArch();
if ("32".equals(arch))
{
System.err.println("Try adding '-d64' to your command line arguments");
}
else if ("64".equals(arch))
{
System.err.println("Try adding '-d32' to your command line arguments");
}
}
else
{
throw ex;
}
}
}
catch (ClassNotFoundException ex)
{
System.err.println("Launch failed: Failed to find main class - org.intrace.client.gui.TraceClient");
}
catch (NoSuchMethodException ex)
{
System.err.println("Launch failed: Failed to find main method");
}
catch (InvocationTargetException ex)
{
Throwable th = ex.getCause();
if ((th.getMessage() != null) &&
th.getMessage().toLowerCase().contains("invalid thread access"))
{
System.err.println("Launch failed: (SWTException: Invalid thread access)");
System.err.println("Try adding '-XstartOnFirstThread' to your command line arguments");
}
else
{
throw th;
}
}
}
private static ClassLoader getSWTClassloader()
{
ClassLoader parent = TraceClientLoader.class.getClassLoader();
URL.setURLStreamHandlerFactory(new RsrcURLStreamHandlerFactory(parent));
String swtFileName = getSwtJarName();
try
{
URL intraceFileUrl = new URL("rsrc:intrace-ui-wrapper.jar");
URL swtFileUrl = new URL("rsrc:" + swtFileName);
System.err.println("Using SWT Jar: " + swtFileName);
ClassLoader cl = new URLClassLoader(new URL[] {intraceFileUrl, swtFileUrl}, parent);
try
{
// Check we can now load the SWT class
Class.forName("org.eclipse.swt.widgets.Layout", true, cl);
}
catch (ClassNotFoundException exx)
{
System.err.println("Launch failed: Failed to load SWT class from jar: " + swtFileName);
throw new RuntimeException(exx);
}
return cl;
}
catch (MalformedURLException exx)
{
throw new RuntimeException(exx);
}
}
private static String getSwtJarName()
{
// Detect OS
String osName = System.getProperty("os.name").toLowerCase();
String swtFileNameOsPart = osName.contains("win") ? "win" : osName
.contains("mac") ? "osx" : osName.contains("linux")
|| osName.contains("nix") ? "linux" : "";
if ("".equals(swtFileNameOsPart))
{
throw new RuntimeException("Launch failed: Unknown OS name: " + osName);
}
// Detect 32bit vs 64 bit
String swtFileNameArchPart = getArch();
String swtFileName = "swt-" + swtFileNameOsPart + swtFileNameArchPart
+ "-3.6.2.jar";
return swtFileName;
}
private static String getArch()
{
// Detect 32bit vs 64 bit
String jvmArch = System.getProperty("os.arch").toLowerCase();
String arch = (jvmArch.contains("64") ? "64" : "32");
return arch;
}
}
[編輯]如上所述,對於那些尋找 「JAR-在-JAR的類加載器」:它包含在Eclipse的JDT(在Java IDE基於Eclipse)。用archiver打開org.eclipse.jdt.ui_ * version_number * .jar,你會在裏面找到一個文件jar-in-jar-loader.zip。我將其重命名爲jar-in-jar-loader.jar。
intrace-ui.jar - 這是我使用上述過程建立的罐子。你應該可以在任何win32/64,linux32/64和osx32/64上運行這個單獨的jar。
[編輯]此答案現在引用自SWT FAQ。
我找不到在您的網站上與您聯繫的方式,但我無法讓swtjar任務正常工作。我收到錯誤'D:\ My Dropbox \ Java \ kEllyIRClient \ swtjar-build.xml:16:存檔swtjar.jar不存在。 taskdef具有正確的類路徑路徑,因爲如果你改變它,它會抱怨。我不知道如何使這個工作,我寧願使用你的任務,而不是手動實現反射的東西。 – 2012-02-02 23:16:15
你可以發佈一個鏈接到你的完整build.xml(或者至少是你有問題的目標?)。你能不能給我詳細的關於磁盤上文件/文件夾的佈局?讓我知道你的電子郵件地址,我會盡力幫助你。 – mchr 2012-02-03 13:06:05
這是我發佈的問題:http://stackoverflow.com/questions/9107509/unable-to-make-ant-script-with-swtjar/9112334#comment11467319_9112334但自那時起腳本發生了變化。我的電子郵件地址是[email protected] – 2012-02-03 13:31:26