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

Posted

技术标签:

【中文标题】如何使用在所有平台上运行的 SWT 创建可执行 JAR?【英文标题】:How can I creating executable JAR with SWT that runs on all platforms? 【发布时间】:2011-01-03 11:30:30 【问题描述】:

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

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

【问题讨论】:

为什么不为每个平台分发多个可执行文件(如 Eclipse)? 因为 SWT 只占用了应用程序的一小部分:整个东西目前是 30MB。所以我可以要求人们为每个平台下载 32MB,或者下载一个 40MB(用于六个平台)的文件,它可以在任何地方运行。 在 Eclipse 案例中,我们有 10 多个下载,每个 >100MB,它们之间的唯一区别是 SWT jar。我要么想要一个下载,要么想要一个大的主下载和一个小的下载,当我第一次运行应用程序时会自动下载。 您所描述的更多是应用程序提供商而不是用户的问题。作为用户,我更喜欢下载 32MB 的 exec。但我明白你不想这样做:) 我想要的是让安装对用户来说不那么痛苦。我想给他们一个可以在任何支持的平台上运行的文件。如果他们想将应用程序带到下一台计算机/操作系统(例如,64 位 Windows 或新的 Linux 机器),应该可以只复制应用程序并完成它。 【参考方案1】:

看这个,有一个代码示例: Create cross platform java swt application

【讨论】:

【参考方案2】:

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

第 1 步。在清单“主类”中放置引导类

第 2 步。当您的引导类运行时,它会将自己的 jar 和其中的所有 jar 解压缩到一个临时目录中。使用类似于下面的行来获取您自己的 jar。

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

第 3 步。您的引导程序类通过“os.name”属性检测操作系统,并使用此属性从 temp 目录加载适当的 jars

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 JVM 是正确的,在其他 JVM 上则不确定。

这样您只能交付一个 jar,它会自行解压并使用正确的 jar 运行。

【讨论】:

如果你想独立于类加载器的类型,只需使用工厂newInstance(urls, parentClassLoader)方法包装它,然后用Thread.currentThread().setContextClassLoader ()安装新的类加载器。 +1 在一个主目录中创建类路径然后调用另一个目录的有趣想法。【参考方案3】:

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 包含一些有用的参考资料。

【讨论】:

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

针对不同平台使用不同的shell脚本,在脚本中指定特定平台的jar会更方便。

【讨论】:

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

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

【讨论】:

以上是关于如何使用在所有平台上运行的 SWT 创建可执行 JAR?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 SWT 浏览器控件在 Windows 上使用 Mozilla 而不是 IE?

如何在 xp 和 windows 7 上运行 SWT 应用程序

创建跨平台 Java SWT 应用程序

如何制作在所有窗口分辨率下显示相似行为(布局)的 SWT/JFace 对话框

Eclipse中如何配置SWT

java中的idea如何把 写好的程序,变成.exe可执行文件?