拓展阅读
jlink 支持版本
jlink
是从 JDK 9 开始支持的。
有什么用?
jlink
工具会从完整的 JDK 中选择特定的模块和资源,创建一个定制化的运行时环境,这个环境包含了运行你的应用程序所需的所有内容。
以下是 jlink
的一些关键点:
-
自定义运行时:
jlink
创建的是一个自定义的运行时环境,它只包含应用程序运行所需的 JDK 模块和资源。这意味着你可以创建一个比完整 JDK 小得多的运行时环境。 -
无需 JRE:因为
jlink
生成的运行时环境包含了应用程序运行所需的所有 JDK 组件,所以用户不需要在他们的机器上安装 JRE 或 JDK。 -
便携性:生成的
jlink
镜像是自包含的,可以轻松地分发给其他用户,用户可以直接运行镜像中的bin/java
命令来启动你的应用程序。 -
模块化:
jlink
允许你指定需要包含在运行时中的模块,这意味着你可以精确控制哪些 JDK 组件被包含在最终的镜像中。 -
执行性能:对于某些应用程序来说,使用
jlink
生成的自定义运行时可能会比使用完整的 JRE 有更好的启动时间和内存占用。
使用 jlink
创建的运行时镜像可以让用户在没有安装 JRE 的情况下运行你的应用程序,这对于部署和分发 Java 应用程序来说是一个很大的优势。
然而,需要注意的是,你的应用程序只能使用到 jlink
镜像中包含的 JDK 模块和资源,如果应用程序依赖于未包含在镜像中的其他模块或特性,那么它将无法运行。
实战笔记
jlink 镜像
jlink 的命令:
jlink --module-path /path/to/jdk-11/lib --add-modules java.base --output myjlinkimage
windows 命令例子:
本地的 jdk 目录为:D:\tool\jdk\graalvm-jdk-23_windows-x64_bin\graalvm-jdk-23.0.1+11.1\bin\
执行
当前的项目根路径执行
D:\tool\jdk\graalvm-jdk-23_windows-x64_bin\graalvm-jdk-23.0.1+11.1\bin\jlink --module-path "D:\tool\jdk\graalvm-jdk-23_windows-x64_bin\graalvm-jdk-23.0.1+11.1\jmods" --add-modules java.base,jdk.graal.compiler --output myjlinkimage
执行后,项目下可以看到 myjlinkimage 文件夹。
自测发现 graal 需要引入 jdk.graal.compiler
。
maven 项目
我们创建一个最简单的 maven 项目用来测试:
src
├─main
│ ├─java
│ │ └─org
│ │ └─example
│ │ └─jlink
│ │ └─demo
│ │ Main.java
│ │
│ └─resources
└─test
└─java
Main.java 终究是一个 hello world.
pom.xml
这里需要把应用部署为可运行的
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>jlink-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>org.example.jlink.demo.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
jar 包含
当前项目直接
mvn clean package
在 target 下生成 jlink-demo-1.0-SNAPSHOT.jar
可执行 jar。
运行测试
项目根路径下运行
./myjlinkimage/bin/java -jar target/jlink-demo-1.0-SNAPSHOT.jar
直接正常输出:
Hello world!
chat
介绍
jlink
是 Java 提供的一个工具,用于定制和创建特定的运行时镜像(runtime image)。
通过 jlink
,可以从 JDK 中选择所需的模块来构建一个精简的 Java 运行时环境。
这种精简的运行时适用于特定的应用程序,可以显著减少运行时的体积和复杂性。
以下是 jlink
的详细介绍:
1. 核心功能
- 定制运行时环境:只包含应用程序运行所需的 Java 模块。
- 减小体积:通过剔除不必要的模块和功能,显著降低 Java 运行时的体积。
- 优化启动性能:支持对模块进行优化(如压缩或预编译)。
- 平台依赖性:创建的运行时镜像是与构建系统的平台相关的。
2. 主要特性
- 模块化支持:基于 Java 平台模块系统(JPMS),选择性地包含模块。
- 跨平台支持:支持在指定平台上构建定制运行时镜像。
- 压缩:支持通过各种压缩方法(如
—compress
参数)减小镜像大小。 - 去除调试信息:通过参数移除运行时不需要的调试信息。
3. 使用场景
- 嵌入式应用开发:在资源受限的设备上运行 Java 应用(如 IoT 设备)。
- 独立应用程序发布:创建只包含必要模块的可执行包,不需要完整的 JDK 或 JRE。
- 云端应用优化:为容器化或无服务器环境构建更轻量级的 Java 环境。
4. 基本命令
(1)语法
jlink --module-path <路径> --add-modules <模块名> [其他选项] --output <目标路径>
(2)常用选项
--module-path
:指定模块路径,通常为 JDK 的jmods
目录。--add-modules
:指定需要包含的模块,模块名以逗号分隔。--output
:指定输出的运行时镜像目录。--compress
:设置压缩级别(0
、1
、2
)。--strip-debug
:移除调试信息。--no-header-files
:不包含头文件。--no-man-pages
:不包含手册页。
5. 示例
(1)构建包含特定模块的运行时镜像
假设需要创建一个运行时镜像,包含 java.base
和 java.sql
模块:
jlink --module-path $JAVA_HOME/jmods \
--add-modules java.base,java.sql \
--output custom-runtime
(2)启用压缩和移除调试信息
jlink --module-path $JAVA_HOME/jmods \
--add-modules java.base,java.sql \
--compress=2 --strip-debug \
--output custom-runtime
(3)运行生成的镜像
生成的运行时镜像会包含一个自定义的 bin
目录和启动脚本,可以直接运行:
./custom-runtime/bin/java -version
6. 文件结构
生成的运行时镜像结构如下:
custom-runtime/
├── bin/ # 包含启动脚本(如 java)
├── conf/ # 配置文件目录
├── include/ # C/C++ 头文件(可选)
├── jmods/ # 模块文件(可选)
├── legal/ # 授权文件
└── lib/ # 必要的库和资源
7. 优势
- 高效:生成的运行时仅包含必要模块,减少了无关部分。
- 安全:移除未使用的模块可以减少潜在的安全漏洞。
- 便携性:自定义运行时镜像无需额外安装 JDK 或 JRE。
8. 限制
- 模块依赖管理复杂:需要明确知道应用所需的模块及其依赖关系。
- 平台相关:生成的运行时镜像与构建时的平台相关,无法跨平台使用。
- 不支持动态加载模块:运行时的模块集是固定的。
9. 小结
jlink
是 Java 模块化的重要工具,特别适合需要精简、优化的场景。
与传统的 JDK 或 JRE 不同,它提供了按需裁剪的能力,可以更好地满足嵌入式、微服务等场景的需求。
参考资料
https://github.com/orphan-oss/launch4j-maven-plugin/blob/master/src/main/resources/README.adoc