從 JDK 9 開始,Oracle JDK 和 OpenJDK 不再默認包含獨立的 JRE 目錄,而是提供了 jlink
工具(Java 鏈接器),允許你根據需求自定義生成最小化的 JRE(包含必要的模塊)。以下是使用 jlink
生成 JRE 的具體步驟:
生成 JRE 的步驟
1. 查看 JDK 包含的模塊(可選)
首先,可通過 jdeps
或 java --list-modules
查看 JDK 中可用的模塊,確定需要包含在 JRE 中的核心模塊(如 java.base
是必選模塊):
# 列出 JDK 所有模塊
java --list-modules
包括一些基礎模塊:
java.base
:核心模塊(String、集合、IO 等),所有 Java 程序都必須依賴,jlink
會自動包含(即使不顯式指定)。java.logging
:日志基礎支持(Spring 內部日志適配依賴)。java.sql
:若應用使用關系型數據庫(如 MySQL、PostgreSQL),需保留(JDBC 依賴)。java.transaction
:事務管理支持(Spring 事務依賴javax.transaction
相關類)。java.xml
:XML 解析支持(Spring 配置文件、XML 格式處理依賴)。java.net.http
:若使用 JDK 內置 HTTP 客戶端(如 Spring 的RestTemplate
底層可能間接用到)。java.management
:JMX 支持(Spring Boot Actuator 監控依賴)。jdk.unsupported
:部分第三方庫(如 Netty)可能依賴其中的非標準 API(謹慎剔除)。
以下模塊多用于桌面應用、廢棄技術或特定場景,服務器端應用通常不需要:
模塊名 | 用途 | 剔除理由 |
---|---|---|
java.desktop | 桌面 GUI(Swing、AWT 等) | Spring 是服務器端框架,無需 GUI 功能 |
java.scripting | 腳本引擎(如 Nashorn) | 不使用腳本動態執行邏輯時可剔除 |
java.rmi | 遠程方法調用(RMI) | 現代 Spring 應用多用 REST/RPC,極少用 RMI |
java.corba | CORBA 協議支持(已廢棄) | 早已被淘汰,Spring 無相關依賴 |
java.xml.ws | JAX-WS(SOAP 服務) | 若不開發 SOAP 服務,僅用 REST 可剔除 |
java.xml.bind | JAXB(XML 綁定) | 現代應用多用 JSON(Jackson),無需 XML 綁定 |
java.prefs | 偏好設置 API | 服務器端應用無需用戶偏好配置 |
java.awt.headless | 無頭模式(非 GUI 環境) | 雖與服務器相關,但 java.desktop 包含它,剔除 java.desktop 即可 |
jdk.jfr | 飛行記錄器(性能監控) | 生產環境若不啟用 JFR,可剔除 |
jdk.jconsole | 控制臺監控工具 | 開發工具,生產 JRE 無需包含 |
jdk.jvisualvm | 可視化監控工具 | 同上,僅開發用 |
jdk.management.agent | JMX 代理 | 若不暴露遠程 JMX 監控,可剔除 |
有寫模塊在特定場景下需要,需結合業務判斷:
java.naming
:JNDI 支持(若應用部署在傳統 Java EE 容器,可能需要;Spring Boot 獨立部署可剔除)。java.security.jgss
:GSSAPI 安全認證(若不涉及 Kerberos 等復雜認證,可剔除)。java.net
:基礎網絡 API(核心模塊依賴,無法單獨剔除,但部分子功能可忽略)。jdk.net
:高級網絡功能(如 HTTP/2),若應用僅用 HTTP/1.1 可剔除。
2. 使用 jlink
生成 JRE
基本命令格式:
jlink --module-path <模塊路徑> --add-modules <需要包含的模塊> --output <生成的JRE目錄>
--module-path
:指定模塊路徑,通常為 JDK 安裝目錄下的jmods
文件夾(如$JAVA_HOME/jmods
)。--add-modules
:指定需要包含的模塊(多個模塊用逗號分隔,java.base
是必須的)。--output
:指定生成的 JRE 存放目錄(如./myjre
)。
高級選項(可選)
-
壓縮 JRE 體積:使用
--compress
選項壓縮模塊(0
不壓縮,1
常量字符串壓縮,2
完全壓縮):
jlink --module-path "$JAVA_HOME/jmods" --add-modules java.base --output myjre --compress 2
在較新的 JDK 版本(如 JDK 21+)中,jlink 的 --compress 參數確實已被標記為廢棄(deprecated),并推薦使用更靈活的 --compress-level 參數替代。這一變化是為了統一壓縮相關的參數命名和功能。
–compress-level 參數的功能與原 --compress 一致,但命名更清晰,支持的壓縮級別范圍相同(0-2):
–compress-level 0:不壓縮(默認值)。
–compress-level 1:僅壓縮常量池(字符串等),平衡體積和性能。
–compress-level 2:完全壓縮(包括指令和常量池),體積最小但構建時間稍長。
-
排除調試信息:使用
--strip-debug
移除調試符號,減小體積:jlink --module-path "$JAVA_HOME/jmods" --add-modules java.base --output myjre --strip-debug
-
設置啟動器:使用
--launcher
為應用創建自定義啟動腳本:jlink --module-path "$JAVA_HOME/jmods" --add-modules java.base \--launcher myapp=java.base/com.example.MyMain \--output myjre
經驗證,構建包含 20 個 modules 的 jre,大小約為 90M,zip 壓縮后為 30M。
注意事項
- 模塊依賴:
jlink
會自動包含指定模塊的依賴模塊(如添加java.desktop
會自動包含其依賴的java.base
、java.xml
等),無需手動添加所有依賴。 - 應用兼容性:生成 JRE 時需確保包含應用所需的所有模塊,可通過
jdeps -s <你的應用.jar>
分析應用依賴的模塊,再按需添加。 - 跨平臺支持:
jlink
只能生成當前平臺(如 Windows x64)的 JRE,跨平臺生成需在對應平臺的 JDK 中執行命令。
通過 jlink
生成的 JRE 是輕量且定制化的,僅包含必要的模塊,適合在生產環境中部署,減少資源占用。