jlink 打包当前平台的二进制文件

问题描述

我正在尝试构建使用 Java 11 构建并使用 jlink 打包的应用程序的跨平台存档。

对于跨平台打包,我的构建基于 this answer。我已经设法让我的 Gradle 构建下载目标平台的 JDK 并使用适当的 jlink 文件夹调用 jmods,但是目标映像始终包含主机平台的二进制文件和 JRE 结构(在我的情况下为 Windows ,这意味着生成的 bin 文件夹始终包含 DLL 和 Windows 可执行文件)。如果我提供 --strip-native-commands 标志,则根本不包含任何可执行文件,尽管 DLL 仍然包含。

有没有办法让 jlink 打包正确的 JRE 文件?

主机 JDK: Windows Oracle JDK 11.0.10 x64

目标 JDK: OpenJDK 11.0.2 x64

Linux 调用示例:

C:\Program Files\Java\jdk-11.0.10/bin/jlink.exe
  --module-path C:\projectdir\build\install\project-linux\lib;C:\projectdir\build\JREs\linux\jmods
  --add-modules com.acme.app
  --compress 2
  --launcher app=com.acme.app/com.acme.app.Main
  --no-header-files
  --no-man-pages
  --strip-debug
  --dedup-legal-notices=error-if-not-same-content
  --output C:\projectdir\build\packageFiles\linux

GraalVM

使用 GraalVM CE Java 11 21.0.0 收益:

java.io.IOException: Invalid JMOD file: C:\jdks\graalvm-ce-java11-21.0.0\jmods\java.base.jmod

这使得 GraalVM 的 jlink 似乎总是尝试使用主机的 JMOD 文件。

OpenJDK

使用 OpenJDK 11.0.2 x64 会产生与在创建的运行时映像中包含主机的二进制文件相同的结果。 Zulu OpenJDK 11.0.10+9 x64 也是如此。

解决方法

发现问题:问题出在我对 Linux 和 MacOS JDK 发行版的 jmods 目录的引用。

对于 Linux 版本,我错误地将构建设置为下载版本 11.0.1 而不是 11.0.2,这最终导致了将层次结构展平而不是展平的逻辑。这意味着 build/JREs/linux/jmods 引用没有针对任何现有文件夹,这意味着 jlink 在那里找不到 JDK 模块,因此包含了主机文件。

MacOS JDK 具有完全不同的文件结构,因此扁平化逻辑是错误的。最终这会导致相同的 jmods 文件夹丢失症状。

修复了这两个问题后,jlink 工具现在可以在构建跨平台运行时映像时正确打包目标 JDK 的文件。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...