如何使用SWT创建可在所有平台上运行的可执行JAR文件?

12

SWT带有一个基础JAR和每个平台(Windows,Linux/32位,Linux/64位,Mac,AIX等)的一个特定JAR。如何创建一个可执行的JAR文件,在运行时选择正确的平台JAR?

[编辑] 我想提供所有平台JAR在一个子目录中,并在main()中修改类加载器。有没有人已经尝试过这样做?


1
为什么不像Eclipse一样为每个平台分发多个可执行文件呢? - Pascal Thivent
因为 SWT 只占应用程序的一小部分:整个应用程序目前只有30MB。所以我可以要求人们为每个平台下载32MB,或者下载一个适用于六个平台的单个40MB文件,可以在任何地方运行。 - Aaron Digulla
在 Eclipse 的情况下,我们有 10 多个下载,每个下载都大于 100MB,它们之间唯一的区别就是 SWT jar。我要么想要一个单一的下载,要么想要一个主要的大下载和每个平台的小下载,在第一次运行应用程序时自动下载。 - Aaron Digulla
你所描述的更多是应用程序提供者的问题,而不是用户的问题。作为用户,我更喜欢下载一个32MB的可执行文件。但我理解你不想这样做 :) - Pascal Thivent
我想要的是让用户安装过程更加轻松。我希望给他们一个适用于任何支持的平台的单个文件。如果他们想要将应用程序带到下一台计算机/操作系统(例如,64位Windows或新的Linux系统),只需复制应用程序即可完成。 - Aaron Digulla
5个回答

6

为了我的现职,我需要提供一个可执行的jar文件,它可以在自身内部加载jar文件并执行第二个main()方法。基本上是有一个引导main()方法和一个应用程序main()方法。

步骤1:在清单“main-class”中放置引导类。

步骤2:当你的引导类运行时,它会将自己的jar文件及其内部所有jar文件解压到一个临时目录中。使用以下类似的代码来获取你自己的jar文件。

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

第三步。您的引导类通过“os.name”属性检测操作系统,并从临时目录加载适当的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});
}

第四步。现在,您应该能够通过调用应用程序的main()函数来运行应用程序。

注意:这个小技巧取决于您的JVM是否使用URLClassLoader作为其SystemClassLoader,在Sun JVM中是正确的,但其他JVM可能不一定如此。

这样,您可以只交付一个单独的jar文件,它将自动解压并使用正确的jar文件运行。


1
如果你想独立于类加载器的类型,只需使用工厂 newInstance(urls, parentClassLoader) 方法进行包装,然后使用 Thread.currentThread().setContextClassLoader() 安装新的类加载器。 - Aaron Digulla
+1 在一个主函数中创建类路径,然后调用另一个函数的想法很有趣。 - Aaron Digulla

5

1

据我所知,您仍然需要解决指定特定平台的JNI库的问题。您可以尝试利用Java Web Start来解决这个问题,但我还没有尝试过。另外,一些项目会为支持的平台构建自定义安装程序。例如,在Mac OS X上部署SWT应用程序描述了如何构建SWT Mac应用程序包的方法。该方法在此示例中使用。我也看到过使用JarBundler Ant Task 的情况。

补充说明:文章在Java Webstart上部署SWT应用程序包括一些有用的参考资料。


我现在尝试使用URLClassLoader,但是有两个问题:如果JAR不在MANIFEST.MF中的ClassPath中,则加载DLL将失败。这意味着我必须同时添加所有 SWT JAR到类路径中。这会导致32位和64位DLL都可见,加载任何一个都会失败。叹气最终,我将添加所有JAR到类路径中,但只复制单个SWT JAR到lib目录中。这样,只有一个JAR会被加载。 - Aaron Digulla
我能看到技术上的吸引力,但我也能看到维护上的困难。面对类似的问题,我添加了一个链接到一个提到JWS的SO文章。 - trashgod

0

0

对于不同的平台,使用不同的shell脚本,并在脚本中指定特定于平台的jar包将更加容易。


我可以编写shell脚本,但我真的希望避免这样做。我的当前解决方案(将所有SWT JAR添加到类路径中,但仅将正确的JAR复制到lib目录中)有效。现在,我只需要编写一个安装程序 :) - Aaron Digulla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接