Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I have a working implementation which is now referenced from the <a href="http://www.eclipse.org/swt/faq.php#multiplatformjar">SWT FAQ</a>.</p> <p>This approach is now available to use as an ANT task: <a href="http://mchr3k.github.com/swtjar/">SWTJar</a></p> <p>[EDIT] SWTJar has now been updated to use Alexey Romanov's solution as described above.</p> <p><a href="https://github.com/mchr3k/org.intrace/blob/master/org.intrace/build.xml">build.xml</a></p> <p>First I build a jar containing all of my application classes.</p> <pre><code>&lt;!-- UI (Stage 1) --&gt; &lt;jarjar jarfile="./build/tmp/intrace-ui-wrapper.jar"&gt; &lt;fileset dir="./build/classes" includes="**/shared/*.class" /&gt; &lt;fileset dir="./build/classes" includes="**/client/gui/**/*.class" /&gt; &lt;zipfileset excludes="META-INF/*.MF" src="lib/miglayout-3.7.3.1-swt.jar"/&gt; &lt;/jarjar&gt; </code></pre> <p>Next, I build a jar to contain all of the following:</p> <ul> <li>JARs <ul> <li>The jar which I just built</li> <li>All the SWT jars</li> </ul></li> <li>Classes <ul> <li>The "Jar-In-Jar" classloader classes</li> <li>A special loader class - see below</li> </ul></li> </ul> <p>Here is the fragment from build.xml.</p> <pre><code>&lt;!-- UI (Stage 2) --&gt; &lt;jarjar jarfile="./build/jars/intrace-ui.jar"&gt; &lt;manifest&gt; &lt;attribute name="Main-Class" value="org.intrace.client.loader.TraceClientLoader" /&gt; &lt;attribute name="Class-Path" value="." /&gt; &lt;/manifest&gt; &lt;fileset dir="./build/classes" includes="**/client/loader/*.class" /&gt; &lt;fileset dir="./build/tmp" includes="intrace-ui-wrapper.jar" /&gt; &lt;fileset dir="./lib" includes="swt-*.jar" /&gt; &lt;zipfileset excludes="META-INF/*.MF" src="lib/jar-in-jar-loader.jar"/&gt; &lt;/jarjar&gt; </code></pre> <p><a href="https://github.com/mchr3k/org.intrace/blob/master/org.intrace/src/org/intrace/client/loader/TraceClientLoader.java">TraceClientLoader.java</a></p> <p>This loader class uses the jar-in-jar-loader to create a ClassLoader which loads classes from two jars.</p> <ul> <li>The correct SWT jar</li> <li>The application wrapper jar</li> </ul> <p>Once we have this classloader we can launch the actual application main method using reflection.</p> <pre><code>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&lt;?&gt; 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) &amp;&amp; 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; } } </code></pre> <p>[EDIT] As stated above, for those looking for the "jar-in-jar classloader": It's included in Eclipse's JDT (the Java IDE built on Eclipse). Open org.eclipse.jdt.ui_*version_number*.jar with an archiver and you will find a file jar-in-jar-loader.zip inside. I renamed this to jar-in-jar-loader.jar.</p> <p><a href="https://github.com/downloads/mchr3k/org.intrace/intrace-ui.jar">intrace-ui.jar</a> - this is the jar which I built using the process described above. You should be able to run this single jar on any of win32/64, linux32/64 and osx32/64.</p> <p>[EDIT] This answer is now referenced from the <a href="http://www.eclipse.org/swt/faq.php#multiplatformjar">SWT FAQ</a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload