jlink是一个 JDK 工具,用于为您的应用程序创建定制的最小 JRE。让我们用“Hello, world!”来试试吧 程序:
class Main { public static void main(String... args) { System.out.println("Hello, world!"); } }
|
我的笔记本电脑是 M1 Mac,我已经为其下载了 Azul Zulu JDK 19 版本。使用 JDK,我既可以编译 Java,又可以运行生成的程序。$ mkdir out $ zulu19.30.11-ca-jdk19.0.1-macosx_aarch64/bin/javac -d out in/Main.java $ zulu19.30.11-ca-jdk19.0.1-macosx_aarch64/bin/java -cp out Main Hello, world!
|
Azul Zulu 还提供了一个 JRE,我可以使用它来运行已编译的程序。$ zulu19.30.11-ca-jre19.0.1-macosx_aarch64/bin/java -cp out Main Hello, world!
|
请注意文件夹名称的细微变化(“jdk”→“jre”)。如果我们将其发送给最终用户,那么二进制大小将很容易获胜。
$ du -hs zulu* 329M zulu19.30.11-ca-jdk19.0.1-macosx_aarch64 136M zulu19.30.11-ca-jre19.0.1-macosx_aarch64
|
但是 136MiB 只是打印几个字“Hello, world”?
值得庆幸的是,jlink它可以帮助我们构建一个只包含我们需要的最小 JRE。给定我们的程序,一个同级工具jdeps列出了所需的 Java 模块。
$ zulu19.30.11-ca-jdk19.0.1-macosx_aarch64/bin/jdeps \ --print-module-deps \ out/Main.class
|
我们的程序非常简单,只需要“基础”模块。现在jlink我们可以生成最小的 JRE。
$ zulu19.30.11-ca-jdk19.0.1-macosx_aarch64/bin/jlink \ --compress 2 \ --strip-debug \ --no-header-files \ --no-man-pages \ --output zulu-hello-jre \ --add-modules java.base
$ du -hs zulu* 28M zulu-hello-jre 329M zulu19.30.11-ca-jdk19.0.1-macosx_aarch64 136M zulu19.30.11-ca-jre19.0.1-macosx_aarch64
|
28MiB 不会赢得任何语言战争,但它比完整的 JRE 节省了 80%。
$ zulu-hello-jre/bin/java -cp out Main Hello, world!
|
我们可以将它运送给我们的客户并收工,对吧?
$ tar -czf hello.tgz zulu-hello-jre out
$ scp hello.tgz jw@server: hello.tgz 100% 14MB 2.0MB/s 00:07
$ ssh jw@server "tar xzf hello.tgz && zulu-hello-jre/bin/java -cp out Main" bash: zulu-hello-jre/bin/java: cannot execute binary file: Exec format error
|
不!虽然我们编译的 Java 字节码是独立于平台的,但 JRE 是特定于每个平台的,而且我的服务器运行 Linux x64。
值得庆幸的是,jlink可以在不同平台的 JDK 上运行。让我们下载 Linux x64 JDK 并jlink使用--module-path.
$ zulu19.30.11-ca-jdk19.0.1-macosx_aarch64/bin/jlink \ --compress 2 \ --strip-debug \ --no-header-files \ --no-man-pages \ --output zulu-hello-jre-linux-x64 \ --module-path zulu19.30.11-ca-jdk19.0.1-linux_x64/jmods --add-modules java.base
$ du -hs zulu* 28M zulu-hello-jre 36M zulu-hello-jre-linux-x64 338M zulu19.30.11-ca-jdk19.0.1-linux_x64 329M zulu19.30.11-ca-jdk19.0.1-macosx_aarch64 136M zulu19.30.11-ca-jre19.0.1-macosx_aarch64
|
Linux x64 JRE 比我的 ARM Mac 大一点,但与全尺寸 JRE 相比仍然小。它对客户端有效吗?
$ tar -czf hello-linux.tgz zulu-hello-jre-linux-x64 out
$ scp hello-linux.tgz jw@server: hello.tgz 100% 16MB 2.1MB/s 00:08
$ ssh jw@server "tar xzf hello-linux.tgz && zulu-hello-jre-linux-x64/bin/java -cp out Main" Hello, world!
|
有用!现在我们可以为任何平台的任何体系结构获取 JDK,并使用我们的主机jlink为每个目标有效地交叉编译最小的 JRE。
对于多架构 Docker 容器、JetBrains Compose UI 等桌面客户端、运送到无法安装完整 JDK 的设备等,这是一个很好的解决方案。