将 JavaFX 应用程序与 openjdk 11 + 运行时捆绑在一起
Bundle JavaFX app with openjdk 11 + runtime
我创建了一个依赖 OpenJDK 11 和 JavaFX 的小型 HelloWorld Java 应用程序。该应用程序打包在一个 jar 文件中,如果我在我的系统上分别安装了 Java 11 和 JavaFX,则该文件只能是 运行。
现在我想将我的 jar 转换成 self-contained Java application,其中包括 JavaFX 和功能齐全的 Java 运行time 环境。这将允许我 运行 我的应用程序而无需安装 OpenJDK 11(它存在技术障碍,例如正确设置 PATH 等)。
我可以找到有关在 Java 10 上创建自包含 Java 应用程序的信息,但我找不到有关将 Java 应用程序与 OpenJDK 11 和 Java 捆绑在一起的信息外汇.
如何使用 OpenJDK 11 和 JavaFX 发布独立的 Java 应用程序(包括 java 运行 时间)?
也许您只需稍等片刻,直到新 jpackager 工具的第一个 EA 版本可用。参见 http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-October/056186.html
您可以将整个 JDK 与您的应用捆绑在一起,并使用捆绑的 JDK 创建批处理脚本 运行 您的应用。我知道这种方法会使您的版本显着膨胀,但另一种方法是要求您的用户自己安装 JDK,这对于不懂技术的人来说并非易事。或者您可以发布两个版本,一个捆绑 JDK,一个不捆绑。
本地库
我遇到的一个挑战是告知 JavaFX 它自己的本地库(.dll
、.dylib
、.so
等)。幸运的是,加载动态库就像使用 System.setProperty(...)
.
设置 java.library.path
一样简单
从历史上看,设置此变量 argued/perceived 在 Java 中毫无意义,因为它对类加载器来说为时已晚(不如 -Djava.library.path
)并且使用反射强制它是 forbidden security violation since Java 10... fortunately, JavaFX actually honors this variable naturally 没有任何违规行为或黑客攻击,设置后会把它捡起来。
// 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
文件也需要可访问。我这样做与 zipping them into the distribution 的任何 java 捆绑相同(制作一个大的 .jar
文件)
这些 .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 11 或更高版本设置 java.library.path
。 Java 8 是个人使用 EOL 2019 年 12 月(商业用途 EOL 2019 年 1 月),因此在客户从一个 LTS 版本迁移到另一个 LTS 版本时提供兼容性很重要。
模块化Java、jlink、&jpackage
关注 these tutorials found at the new home for JavaFX after having been spun out of Oracle to Gluon.
您将需要使用模块化编写代码 Java。添加 JavaFX 11 作为项目的依赖项。并使用新的 linking/packaging 工具在您的应用程序中捆绑 JDK 的一个子集。
了解:
- Java Platform Module System
- jlink (JEP 282)
- jpackage (JEP 343)
不再有 JRE
Oracle 不再打算让最终用户安装 JRE 或 JDK。 Java Applets in a browser and Java Web Start 应用程序交付都被逐步淘汰,最终用户不再需要 JRE。基于 Java 的应用程序应该捆绑自己的 Java 实现。唯一有意识地安装 JDK 的人将是开发人员和服务器端系统管理员。
重要:
- 认清OpenJDK project, as explained in Wikipedia的本质。
- 知道 Oracle 已承诺在其自有品牌 Oracle JDK 和 OpenJDK 项目。此承诺包括捐赠以前的商业功能,例如 Flight Recorder and Mission Control.
- OpenJFX, the open-source development of JavaFX, is a part of the OpenJDK project. OpenJFX may or may not be included in a build of OpenJDK. The Java specifications 不需要 JavaFX 功能。
- 至少有两家供应商提供了与 OpenJFX 库捆绑在一起的 JDK 产品版本:
- ZuluFX 来自 Azul Systems
- 来自 BellSoft
的 LibericaFX
- 阅读 Oracle 2018-03 的这份白皮书,Java Client Roadmap Update
- 阅读由 Java 社区的主要成员撰写的白皮书 Java Is Still Free。
这是一个流程图,可以帮助您在提供 Java 11 实施的各个供应商中找到并做出决定。
(使用 jdk14)
首先,为了使用 jlink
你的主 jar 应该是一个模块。
如何? 假设您有一个 maven
项目。您只需要在 src/main/java
目录中包含 module-info.java
并确保您 require
您的应用程序需要的模块和 export
包含您的主要内容的包 class.在大多数情况下,缺少 requires
时会出现编译时错误。请记住,非模块化依赖项变为 .
您可以使用 Maven 的 copy-dependencies
来确保在 mvn package
.
期间将所有依赖项都复制到 target/lib
下
下一步:jlink
因为jlink
maven插件还在alpha
,你可以使用命令行。
备注:
jlink
将创建一个独立的包目录,其中包含
- 主应用程序模块
- 应用依赖项
- jdk 所需模块
- 应用程序启动器(可选)
jlink
捆绑包针对 一次一个平台 。 默认它是当前平台。
javafx
运行时间模块也是平台特定的。但由于它们不是jdk的一部分,我们需要始终提供包含它们的模块路径。
javafx
运行时间模块可以downloaded from web, or from maven repo使用相应的目标平台classifier
(win/linux/mac).
jlink
还可以创建 跨平台包 。只需将目标平台模块包含到 --module-path
(例如来自 linux:下载 windows jdk
/ javafx
并将它们的 jmods
目录添加到 module-path
).
jlink 命令
案例 1:build 和 target 平台 相同
注意:/path-to/javafx-mods
需要提供给您的 modulepath
,除非您使用 Maven(复制依赖项)在 lib/
下复制所需的 javafx deps。
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:build 和 target 平台 不同
# 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
我创建了一个依赖 OpenJDK 11 和 JavaFX 的小型 HelloWorld Java 应用程序。该应用程序打包在一个 jar 文件中,如果我在我的系统上分别安装了 Java 11 和 JavaFX,则该文件只能是 运行。
现在我想将我的 jar 转换成 self-contained Java application,其中包括 JavaFX 和功能齐全的 Java 运行time 环境。这将允许我 运行 我的应用程序而无需安装 OpenJDK 11(它存在技术障碍,例如正确设置 PATH 等)。
我可以找到有关在 Java 10 上创建自包含 Java 应用程序的信息,但我找不到有关将 Java 应用程序与 OpenJDK 11 和 Java 捆绑在一起的信息外汇.
如何使用 OpenJDK 11 和 JavaFX 发布独立的 Java 应用程序(包括 java 运行 时间)?
也许您只需稍等片刻,直到新 jpackager 工具的第一个 EA 版本可用。参见 http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-October/056186.html
您可以将整个 JDK 与您的应用捆绑在一起,并使用捆绑的 JDK 创建批处理脚本 运行 您的应用。我知道这种方法会使您的版本显着膨胀,但另一种方法是要求您的用户自己安装 JDK,这对于不懂技术的人来说并非易事。或者您可以发布两个版本,一个捆绑 JDK,一个不捆绑。
本地库
我遇到的一个挑战是告知 JavaFX 它自己的本地库(.dll
、.dylib
、.so
等)。幸运的是,加载动态库就像使用 System.setProperty(...)
.
java.library.path
一样简单
从历史上看,设置此变量 argued/perceived 在 Java 中毫无意义,因为它对类加载器来说为时已晚(不如 -Djava.library.path
)并且使用反射强制它是 forbidden security violation since Java 10... fortunately, JavaFX actually honors this variable naturally 没有任何违规行为或黑客攻击,设置后会把它捡起来。
// 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
文件也需要可访问。我这样做与 zipping them into the distribution 的任何 java 捆绑相同(制作一个大的 .jar
文件)
这些 .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 11 或更高版本设置 java.library.path
。 Java 8 是个人使用 EOL 2019 年 12 月(商业用途 EOL 2019 年 1 月),因此在客户从一个 LTS 版本迁移到另一个 LTS 版本时提供兼容性很重要。
模块化Java、jlink、&jpackage
关注 these tutorials found at the new home for JavaFX after having been spun out of Oracle to Gluon.
您将需要使用模块化编写代码 Java。添加 JavaFX 11 作为项目的依赖项。并使用新的 linking/packaging 工具在您的应用程序中捆绑 JDK 的一个子集。
了解:
- Java Platform Module System
- jlink (JEP 282)
- jpackage (JEP 343)
不再有 JRE
Oracle 不再打算让最终用户安装 JRE 或 JDK。 Java Applets in a browser and Java Web Start 应用程序交付都被逐步淘汰,最终用户不再需要 JRE。基于 Java 的应用程序应该捆绑自己的 Java 实现。唯一有意识地安装 JDK 的人将是开发人员和服务器端系统管理员。
重要:
- 认清OpenJDK project, as explained in Wikipedia的本质。
- 知道 Oracle 已承诺在其自有品牌 Oracle JDK 和 OpenJDK 项目。此承诺包括捐赠以前的商业功能,例如 Flight Recorder and Mission Control.
- OpenJFX, the open-source development of JavaFX, is a part of the OpenJDK project. OpenJFX may or may not be included in a build of OpenJDK. The Java specifications 不需要 JavaFX 功能。
- 至少有两家供应商提供了与 OpenJFX 库捆绑在一起的 JDK 产品版本:
- ZuluFX 来自 Azul Systems
- 来自 BellSoft 的 LibericaFX
- 阅读 Oracle 2018-03 的这份白皮书,Java Client Roadmap Update
- 阅读由 Java 社区的主要成员撰写的白皮书 Java Is Still Free。
这是一个流程图,可以帮助您在提供 Java 11 实施的各个供应商中找到并做出决定。
(使用 jdk14)
首先,为了使用 jlink
你的主 jar 应该是一个模块。
如何? 假设您有一个 maven
项目。您只需要在 src/main/java
目录中包含 module-info.java
并确保您 require
您的应用程序需要的模块和 export
包含您的主要内容的包 class.在大多数情况下,缺少 requires
时会出现编译时错误。请记住,非模块化依赖项变为
您可以使用 Maven 的 copy-dependencies
来确保在 mvn package
.
target/lib
下
下一步:jlink
因为jlink
maven插件还在alpha
,你可以使用命令行。
备注:
jlink
将创建一个独立的包目录,其中包含- 主应用程序模块
- 应用依赖项
- jdk 所需模块
- 应用程序启动器(可选)
jlink
捆绑包针对 一次一个平台 。 默认它是当前平台。javafx
运行时间模块也是平台特定的。但由于它们不是jdk的一部分,我们需要始终提供包含它们的模块路径。javafx
运行时间模块可以downloaded from web, or from maven repo使用相应的目标平台classifier
(win/linux/mac).jlink
还可以创建 跨平台包 。只需将目标平台模块包含到--module-path
(例如来自 linux:下载 windowsjdk
/javafx
并将它们的jmods
目录添加到module-path
).
jlink 命令
案例 1:build 和 target 平台 相同
注意:/path-to/javafx-mods
需要提供给您的 modulepath
,除非您使用 Maven(复制依赖项)在 lib/
下复制所需的 javafx deps。
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:build 和 target 平台 不同
# 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