如何为没有本机安装程序的使用 JavaFX 的应用程序制作可运行的 jar

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23117541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 20:50:16  来源:igfitidea点击:

How to make a runnable jar for an application that uses JavaFX without native installers

javaeclipseantjarjavafx

提问by evilfred

I have a application that worked just fine to be run with "java -jar blah.jar" after exporting as a runnable jar from Eclipse and letting it "Package required libraries into generated JAR".

我有一个应用程序,在从 Eclipse 导出为可运行的 jar 并让它“将所需的库打包到生成的 JAR 中”后,可以使用“java -jar blah.jar”运行。

I added some JavaFX code to pop up a web browser. Now it seems it is impossible to make a runnable jar that works across minor Java versions. When I export it as a runnable jar, it copies in jfxrt.jar that is specific to my minor version. If I run this jar using "java -jar blah.jar" for the exact matching java version (jdk1.7.0_17) then it works fine, but if I use one slightly newer (jdk1.7.0_45) then it fails to resolve swingx classes properly. So much for "write once run anywhere".

我添加了一些 JavaFX 代码来弹出 Web 浏览器。现在似乎不可能制作一个跨小 Java 版本运行的可运行 jar。当我将它导出为可运行的 jar 时,它会复制到特定于我的次要版本的 jfxrt.jar 中。如果我使用“java -jar blah.jar”为完全匹配的java版本(jdk1.7.0_17)运行这个jar,那么它工作正常,但如果我使用一个稍微更新的(jdk1.7.0_45)那么它无法解决swingx正确上课。“一次编写,随处运行”就这么多。

I tried to use the JavaFX ant tasks but I can't get the task to actually package up the dependent jars. This doesn't actually include the fx:resources jars in the jar it creates, like the magic eclipse "package required libraries into generated JAR" does perfectly:

我尝试使用 JavaFX ant 任务,但无法获得实际打包依赖 jar 的任务。这实际上并不包括它创建的 jar 中的 fx:resources jar,就像魔术 eclipse“将所需的库打包到生成的 JAR 中”一样:

<fx:jar destfile="${dist}/${dist.jar}"> 
        <fx:application id="BlahTesterApp" 
            mainClass="blah.MainClass" 
            toolkit="swing"/> 

        <fileset dir="${build}"/> 

        <fx:resources> 
            <fx:fileset dir="${lib}" includes="**/*.jar" />
        </fx:resources>

        <manifest> 
            <attribute name="Implementation-Vendor" value="My Team"/>
            <attribute name="Implementation-Title" value="Tester App"/> 
        </manifest> 
    </fx:jar> 

And seems to only be able to create "native bundles" which I don't want. I don't want to make users install an rpm or a deb when they used to just be able to run the darn jar.

并且似乎只能创建我不想要的“本机捆绑包”。我不想让用户在过去只能运行该 jarn jar 时安装 rpm 或 deb。

I don't understand why Oracle had to introduce its own magical extra layer of deployment complexity here. Don't they want people to USE JavaFX?

我不明白为什么 Oracle 必须在这里引入它自己神奇的额外部署复杂层。他们不希望人们使用 JavaFX 吗?

回答by jewelsea

Update, December 2019

更新,2019 年 12 月

As the answer to this topic seems to evolve and change over time (and it looks like it will continue to do so). My advice is to review the documentation at https://openjfx.ioto review latest best practices for packaging JavaFX applications.

因为这个话题的答案似乎随着时间的推移而演变和变化(而且看起来它会继续这样做)。我的建议是查看https://openjfx.io上的文档,查看打包 JavaFX 应用程序的最新最佳实践。

I tried to use the JavaFX ant tasks but I can't get the task to actually package up the dependent jars ... And seems to only be able to create "native bundles" which I don't want.

我尝试使用 JavaFX ant 任务,但我无法完成实际打包依赖 jar 的任务......而且似乎只能创建我不想要的“本机包”。

Current advice from openjfx.io to create a single cross-platform jar for a JavaFX application, which includes dependencies and the cross-platform JavaFX libs is to use a different build tool (e.g. Maven or Gradle rather than Ant).

来自 openjfx.io 的当前建议为 JavaFX 应用程序创建单个跨平台 jar,其中包括依赖项和跨平台 JavaFX 库是使用不同的构建工具(例如 Maven 或 Gradle 而不是 Ant)。

Use the features of those build tools (e.g. the Maven Shade plug-in) to package your dependent jars with your code into an uber-jar.

使用这些构建工具的功能(例如Maven Shade 插件)将您的依赖 jar 和您的代码打包到一个 uber-jar 中。

When doing this, if you want the resultant jar to be cross platform capable, e.g. to work on Window+Mac+Linux, then you need to package all of the cross platform jars as dependencies into the uber-jar (use the appropriate JavaFX version for your project).

执行此操作时,如果您希望生成的 jar 具有跨平台能力,例如在 Window+Mac+Linux 上工作,那么您需要将所有跨平台 jar 作为依赖项打包到 uber-jar 中(使用适当的 JavaFX 版本为您的项目)。

<dependencies>
    ...
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics</artifactId>
        <version>13</version>
        <classifier>win</classifier>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics</artifactId>
        <version>13</version>
        <classifier>linux</classifier>
    </dependency>
    <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-graphics</artifactId>
        <version>13</version>
        <classifier>mac</classifier>
    </dependency>
</dependencies>

The resultant jar will require a more recent Java version to work (e.g. Java 11+).

生成的 jar 将需要更新的 Java 版本才能工作(例如 Java 11+)。



There is currently an incubating project (JEP 343: Packaging Tool), targeted for Java 14, with the following goals (these are different than what is required in the question, as the packaging tool is for creating native installers, which is specifically what the question doesn't want to do):

目前有一个孵化项目(JEP 343:打包工具),针对 Java 14,具有以下目标(这些与问题中要求的不同,因为打包工具用于创建本机安装程序,具体是什么问题不想做):

Create a simple packaging tool, based on the JavaFX javapackager tool, that:

  • Supports native packaging formats to give end users a natural installation experience. These formats include msi and exe on Windows, pkg and dmg on macOS, and deb and rpm on Linux.
  • Allows launch-time parameters to be specified at packaging time.
  • Can be invoked directly, from the command line, or programmatically, via the ToolProvider API.

创建一个基于 JavaFX javapackager 工具的简单打包工具:

  • 支持原生打包格式,为最终用户提供自然的安装体验。这些格式包括 Windows 上的 msi 和 exe,macOS 上的 pkg 和 dmg,以及 Linux 上的 deb 和 rpm。
  • 允许在打包时指定启动时间参数。
  • 可以直接从命令行调用,也可以通过 ToolProvider API 以编程方式调用。

The proposed project exists because:

拟议项目的存在是因为:

To address these requirements previously, a packaging tool called javapackager was distributed with Oracle's JDK 8. However, it was removed from Oracle's JDK 11 as part of the removal of JavaFX.

以前,为了满足这些要求,Oracle 的 JDK 8 随附了一个名为 javapackager 的打包工具。但是,作为 JavaFX 删除的一部分,它已从 Oracle 的 JDK 11 中删除。

Note, due to the update outlined above, until Java 14 is released, some of the packaging recommendations mentioned below (such as javafxpackager) only apply to, now-outdated, older Java distributions (8-10).

请注意,由于上述更新,在 Java 14 发布之前,下面提到的一些打包建议(例如 javafxpackager)仅适用于现已过时的旧 Java 发行版 (8-10)。

Also the advice on not to include Java Platform libraries is outdated. From Oracle Java 8 until Oracle Java 10, JavaFX was included in the base JRE (Java runtime environment). From Java 11 on, JavaFX is not include in the base JRE and, indeed, the platform libraries must be added to the Java module path separately. Again, review https://openjfx.iofor packaging options for JavaFX applications.

此外,关于不包含 Java 平台库的建议已经过时。从 Oracle Java 8 到 Oracle Java 10,JavaFX 包含在基本 JRE(Java 运行时环境)中。从 Java 11 开始,JavaFX 不再包含在基本 JRE 中,实际上,平台库必须单独添加到 Java 模块路径中。再次查看https://openjfx.io以了解 JavaFX 应用程序的打包选项。



Outdated info:

过时的信息:

JavaFX packaging alternatives

JavaFX 包装替代品

  1. Follow the e(fx)clipse tutorialfor creating an executable jar file for a JavaFX application using Eclipse.
  2. The Oracle java packaging ant tasks and javafxpackager tool can create executable jars (described in the Oracle documentation as standalone applications). If you cannot generate such jars using the tools, then you are likely not using the tools correctly.
  3. Require a minimum version of Java 8, where jfxrt.jar (i.e. the JavaFX classes) is on the boot class path.
  4. Use a 3rd party build tool chain such as the JavaFX Maven pluginor the JavaFX Gradle plugin.
  1. 按照e(fx)clipse 教程使用 Eclipse 创建 JavaFX 应用程序的可执行 jar 文件。
  2. Oracle java 打包 ant 任务和 javafxpackager 工具可以创建可执行 jars(在 Oracle 文档中作为独立应用程序描述)。如果您无法使用这些工具生成此类 jar,那么您可能没有正确使用这些工具。
  3. 需要最低版本的 Java 8,其中 jfxrt.jar(即 JavaFX 类)位于引导类路径上。
  4. 使用第 3 方构建工具链,例如JavaFX Maven 插件JavaFX Gradle 插件

Alternative (1), e(fx)clipse packaging, is recommended for you since you are using Eclipse.

由于您使用的是 Eclipse,因此建议您使用替代方案 (1) e(fx)clipse 包装。

Advice

建议

Never try to include Java platform libraries (such as jfxrt.jar) with your application. No guide you find on the internet should ever instruct you to do such a thing (due to the obvious incompatibility between minor version issues you outlined in your question). The only exception to this rule would be if you are building a self-contained, native installed application that doesn't rely on a pre-installed JRE (which you aren't).

切勿尝试在您的应用程序中包含 Java 平台库(例如 jfxrt.jar)。您在互联网上找到的任何指南都不应该指导您做这样的事情(由于您在问题中概述的次要版本问题之间明显不兼容)。此规则的唯一例外是,如果您正在构建一个独立的、本地安装的应用程序,该应用程序不依赖于预安装的 JRE(您不依赖)。