13

我创建了一个依赖 OpenJDK 11 和 JavaFX 的小型 HelloWorld Java 应用程序。该应用程序打包在一个 jar 文件中,只有在我的系统上分别安装了 Java 11 和 JavaFX 时才能运行该文件。

现在我想将我的 jar 转换为一个独立的 Java 应用程序,其中包括 JavaFX 和一个功能齐全的 Java 运行时环境。这将允许我在不安装 OpenJDK 11 的情况下运行我的应用程序(这会带来技术障碍,例如正确设置 PATH 等)。

我可以找到有关在 Java 10 上创建自包含 Java 应用程序的信息,但找不到有关将 Java 应用程序与 OpenJDK 11 和 JavaFX 捆绑在一起的信息。

如何使用 OpenJDK 11 和 JavaFX 发布自包含的 Java 应用程序(包括 Java 运行时)?

4

5 回答 5

16

模块化 Java、jlinkjpackage

在从Oracle分拆到Gluon之后,请按照在JavaFX 的新家中找到的这些教程进行操作。

您将需要使用模块化 Java 编写代码。将 JavaFX 11 作为依赖项添加到您的项目中。并使用新的链接/打包工具将 JDK 的子集捆绑到您的应用程序中。

学习关于:

不再有 JRE

Oracle 不再打算让最终用户安装 JRE 或 JDK。浏览器中的Java 小程序和Java Web Start应用程序交付都将被逐步淘汰,最终用户不再需要 JRE。基于 Java 的应用程序应捆绑自己的 Java 实现。唯一有意识地安装 JDK 的人是开发人员和服务器端系统管理员。

重要的:

  • 清楚地了解OpenJDK项目的性质,如Wikipedia 中所述
  • 知道甲骨文已承诺在其自有品牌的甲骨文 JDKOpenJDK项目之间实现功能平等。该承诺包括捐赠以前的商业功能,例如飞行记录器任务控制
  • OpenJFX是 JavaFX 的开源开发,是OpenJDK项目的一部分。OpenJFX 可能包含也可能不包含在 OpenJDK 的构建中。Java 规范不需要 JavaFX 功能。
  • 至少有两家供应商提供了与 OpenJFX 库捆绑在一起的 JDK 产品版本:
    • Azul Systems 的ZuluFX
    • 来自 BellSoft 的LibericaFX
  • 阅读 Oracle 于 2018 年 3 月发布的这份白皮书,Java 客户端路线图更新
  • 阅读由 Java 社区的主要成员撰写的白皮书Java Is Still Free 。

这是一个流程图,可以帮助您在提供 Java 11 实现的各种供应商中找到并做出决定。

指导您为 Java 11 实施选择供应商的流程图


选择 Java 供应商的动机

于 2019-02-18T00:48:44.810 回答
2

您可以将整个 JDK 与您的应用程序捆绑在一起,并创建一个批处理脚本来使用捆绑的 JDK 运行您的应用程序。我知道这种方法会大大增加您的版本,但另一种方法是要求您的用户自己安装 JDK,这对于非技术人员来说并非易事。或者,您可以同时发布两个版本,一个捆绑 JDK,一个不捆绑。

于 2018-10-24T18:55:43.933 回答
1

也许您只是稍等片刻,直到新的 jpackager 工具的第一个 EA 版本可用。见http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-October/056186.html

于 2018-10-24T15:24:32.593 回答
1

原生库

我遇到的一个挑战是告知 JavaFX 它自己的本机库(.dll.dylib.so等)。幸运的是,加载 dylib 就像设置java.library.pathusing一样简单System.setProperty(...)

从历史上看,设置这个变量在 Java 中被争论/认为是没有意义的,因为它对于类加载器(低于 )来说太晚了,-Djava.library.path并且使用反射强制它是自 Java 10 以来被禁止的安全违规......幸运的是,JavaFX实际上自然地尊重这个变量而没有任何违规或黑客行为,并将在设置后将其拾取。

// Detect the path to the currently running jar
String jarPath = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().getPath()).getCanonicalPath();

// Fix characters that get URL encoded when calling getPath()
jarPath = URLDecoder.decode(jarPath, "UTF-8");

String parentFolder = new File(jarPath).getParent();

// If libglass.dylib is next to the jar in a folder called "/bin"
System.setProperty("java.library.path",  parentFolder + "/bin");

// ... then make any javafx calls

Java 库

当然,这些.jar文件也需要可访问。我通过将它们压缩到分发中(制作单个大.jar文件)来执行与任何 java 捆绑包相同的操作

这些.jar文件应与所有 JavaFX 11 发行版一致,并应进行相应捆绑。

javafx-swt.jar
javafx.base.jar
javafx.controls.jar
javafx.fxml.jar
javafx.graphics.jar
javafx.media.jar
javafx.swing.jar
javafx.web.jar

Java 8 兼容性

使用上述技术对 Java 8 进行的初步测试是肯定的。目前,我正在使用 Java 版本检测(不包括在上面的示例中)并且仅为java.library.pathJava 11 或更高版本设置。Java 8 于 2019 年 12 月停止供个人使用(2019 年 1 月停止用于商业用途),因此在客户端从一个 LTS 版本迁移到另一个版本时提供兼容性非常重要。

于 2019-01-31T05:11:29.687 回答
1

(使用jdk14)

首先,为了使用jlink 你的主 jar 应该是一个模块。

如何?考虑到你有一个maven项目。您只需要包含module-info.javasrc/main/javadir 中并确保您require的应用程序需要的模块以及export包含您的主类的包。在大多数情况下,如果缺少requires. 请记住,非模块化依赖项成为自动模块

您可以使用 mavencopy-dependencies确保所有依赖项都target/libmvn package.

下一步:jlink

由于jlinkmaven 插件还在alpha,所以可以使用命令行。

笔记:

  • jlink将创建一个自包含的包目录,其中包含
    • 主应用模块
    • 应用依赖
    • jdk 所需模块
    • 应用启动器(可选)
  • jlinkbundle 一次只针对一个平台。默认情况下,它是当前平台。
  • javafx运行时模块也是平台特定的。但由于它们不是 jdk 的一部分,我们需要始终提供包含它们的模块路径。
  • javafx运行时模块可以从 web 下载,也可以使用相应的目标平台(win/linux/mac)从 maven repo下载。classifier
  • jlink还可以创建跨平台捆绑包。只需将目标平台模块包含到--module-path(例如从 linux:下载 windows jdk/javafx并将其jmods目录添加到module-path)。

jlink 命令

案例一: 构建平台和目标平台相同

注意:/path-to/javafx-mods需要提供给您,除非您在using maven (copy-dependencies)modulepath下复制所需的 javafx deps 。lib/


jlink --launcher run=jdk14Example/com.example.javafx.app.Main \
--module-path ./lib:javafx-jdk14-example-1.0.0.jar:/path-to/javafx-mods \
--add-modules=jdk14Example --output app-bundle

案例 2: 构建平台和目标平台不同

# Building from linux for windows
jlink --launcher run=jdk14Example/com.example.javafx.app.Main  \
--module-path ./lib:javafx-jdk14-example-1.0.0.jar:/path-to/jdk-win/jmods:/path-to/javafx-mods-win \
--add-modules=jdk14Example --output app-bundle

结论:

在上述两种情况下,您都会获得一个包含独立应用程序的目录,该应用程序可以在没有安装java/的工作站上运行javafx

# if jlink targeted linux
app-bundle/bin/run

# if jlink targeted windows
app-bundle/bin/run.bat

# if jlink targeted mac
app-bundle/bin/run

于 2020-06-30T16:29:28.833 回答