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


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

[编辑]我想在一个子目录中提供所有平台JAR main() 然后会修改类加载器。有没有人试过这个?


10456
2018-01-10 14:08


起源

为什么不为每个平台分发几个可执行文件(Eclipse)? - Pascal Thivent
因为SWT只占应用程序的一小部分:目前整个东西都是30MB。所以我可以要求人们为每个平台下载32MB或下载一个运行到处的40MB(六个平台)文件。 - Aaron Digulla
在eclipse的情况下,我们有10+下载,每个> 100MB,它们之间的唯一区别是SWT jar。我想要一次下载或者一次大的主要下载和每个平台的小型下载,当我第一次运行应用程序时会自动下载。 - Aaron Digulla
您所描述的内容对于应用程序提供商而言比对用户而言更是一个问题。作为用户,我更喜欢下载32MB的exec。但我知道你不想这样做:) - Pascal Thivent
我想要的是让安装减少对用户的痛苦。我想给他们一个适用于任何支持平台的文件。如果他们想将应用程序带到下一台计算机/操作系统(例如,64位Windows或新的Linux机器),应该可以复制应用程序并完成它。 - Aaron Digulla


答案:


看看这个,有一个代码示例: 创建跨平台的java swt应用程序


4
2017-07-23 13:30





对于我目前的工作,我需要提供一个可执行jar,它可以在其自身内加载jar并执行第二个main()。基本上是一个bootstrap main()和一个应用程序main()。

步骤1.在清单“main-class”中放入引导类

第2步。当你的bootstrap类运行时,unjar是自己的jar,里面的所有jar都是temp目录。使用类似下面的行来获得自己的jar。

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

步骤3.您的引导类通过“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});
}

步骤4.现在,您应该可以通过调用应用程序main()来运行应用程序。

注意:这个小小的hack取决于你的JVM使用 URLClassLoader 作为它的SystemClassLoader,对于Sun JVM来说是真的,对其他人来说并不确定。

这样你就可以只交付一个罐子了,它会解压缩并运行正确的罐子。


5
2018-01-11 05:00



如果您想独立于类加载器的类型,只需使用工厂 newInstance(urls, parentClassLoader) 包装它的方法,然后安装新的类加载器 Thread.currentThread().setContextClassLoader ()。 - Aaron Digulla
+1有趣的想法在一个main中创建类路径然后调用另一个。 - Aaron Digulla
@Aaron感谢小费,我将不得不尝试 - karoberts


IIUC,您仍然有指定特定于平台的JNI库的问题。你可以利用 Java Web Start 为此,但我没有尝试过。或者,某些项目为受支持的平台构建自定义安装程序。例如, 在Mac OS X上部署SWT应用程序 介绍如何构建SWT Mac应用程序包。该方法用于此 。我也见过这个 JarBundler Ant任务 用过的。

附录:文章 在Java Webstart上部署SWT应用程序 包括一些有用的参考。


1
2018-01-10 16:40



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


也许 http://one-jar.sourceforge.net/ (Maven插件在 http://code.google.com/p/onejar-maven-plugin/)可以帮助朝这个方向发展......


0
2018-01-10 14:35





为不同的平台使用不同的shell脚本会更容易,并在脚本中指定特定于平台的jar。


0
2018-01-10 20:12



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