使用Jlink在一个平台上为另一个平台创建Java运行时镜像

32

我在Linux机器上使用jlink创建了运行时映像。我看到include文件夹下有linux文件夹。这是否意味着我只能在Linux平台上使用此运行时映像?如果是,是否有办法在一个平台上为另一个平台创建运行时映像(例如,在Linux上为Windows创建,反之亦然)?

2个回答

49

include 目录是用于存放头文件的,例如 jni.h 这样的文件。编译使用 JNI 和其他本地接口的 C/C++ 代码时需要这些头文件。它与 jlink 没有任何关系。

jlink 工具可以为另一个平台创建一个运行时映像(进行交叉目标)。您需要下载两个 JDK 来执行此操作。一个是在运行 jlink 的平台上使用的 JDK,另一个是针对目标平台的 JDK。使用 --module-path $TARGET/jmods 运行 jlink,其中 $TARGET 是您解压用于目标平台的 JDK 的目录。


12

鉴于我无法在信息方面对Alan Bateman的回答进行任何补充,我将提供一个工作示例。此示例说明了如何在Mac OS上使用jlink,然后在Docker容器中的Ubuntu上运行二进制文件。

要点如下:

假设有两个简单模块,我们在Mac OS上进行编译:

javac -d build/modules \
--module-source-path src \
`find src -name "*.java"`

jar --create --file=lib/net.codetojoy.db@1.0.jar \
-C build/modules/net.codetojoy.db . 

jar --create --file=lib/net.codetojoy.service@1.0.jar \
-C build/modules/net.codetojoy.service . 

假设Linux 64位JDK已解压到本地目录(作为命令行参数指定),我们调用jlink(在此示例中为Mac OS)。JAVA_HOME是解决方案的关键:

# $1 is ./jdk9_linux_64/jdk-9.0.1
JAVA_HOME=$1 

rm -rf serviceapp 

jlink --module-path $JAVA_HOME/jmods:build/modules \
--add-modules net.codetojoy.service \
--output serviceapp

假设我们已经从Docker拉取了 ubuntu 映像,我们可以在Docker终端(即Linux)中执行以下操作:

docker run --rm -v $(pwd):/data ubuntu /data/serviceapp/bin/java net.codetojoy.service.impl.UserServiceImpl

TRACER : hello from UserServiceImpl

再次强调Java 9/jlink的这个特性:Linux系统上没有安装Java,而且Linux二进制文件是在Mac OS上构建的。


7
将JAVA_HOME作为变量名是不必要的混淆。将其命名为LINUX_JAVA_HOME或UNPACKED_LINUX_JAVA或者其他任何名称更加清晰易懂。 - Perdi Estaquel
2
对于普通读者来说,Docker 的功能目的是什么?为什么不只是将目标 JDK 提取到本地目录中?此外,请根据上面的注释修复保留的 $JAVA_HOME 变量的不当使用。 - tresf
1
在这里使用Docker会不必要地使事情变得过于复杂。 - Guntram Blohm
5
另一方面,使用 Docker 可以让你在同一台机器上测试新创建的二进制文件,无需使用虚拟机、重新启动或其他操作。 - Dmitry Avtonomov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接