一、前言
隨著Java版本的演進,打包工具也持續更新以適應新的需求和技術。從Java 7到Java 17,打包工具經歷了顯著的變化,涵蓋了模組化、多版本兼容、性能優化以及對Docker容器的更好支持。 本文旨在整理Java 7 至 17 關於打包工具的新特性,包括各版本的更新,以及這些更新所帶來的好處。
目錄
- 一、前言
- 二、Java 7:JAR 包基礎功能改進
- 三、Java 8:無顯著打包工具更新
- 四、Java 9:模組化系統(Project Jigsaw)
- 五、Java 10 - Java 16:打包工具的持續改進
- 六、Java 17:jpackage 工具成為正式功能
- 七、總結
二、Java 7:JAR 包基礎功能改進
Java 7 在打包方面的主要改進集中在JAR(Java Archive)文件格式本身。
-
多版本 JAR 文件:
引入了在同一個 JAR 文件中包含不同版本的類文件的能力。 透過
Multi-Release JAR Files
,Java 7之後的JVM可以根據運行時的版本選擇最適合的類。 -
Manifest 文件改進:
對於 JAR 文件的
META-INF/MANIFEST.MF
文件進行了增強,允許更詳細的元數據描述。
範例:
雖然Java 7引入了多版本JAR的概念,但真正廣泛應用是之後的版本。 這邊僅示範MANIFEST.MF的簡單應用。
這個例子設定了MANIFEST的版本,打包者資訊,和預設執行的類別。
三、Java 8:無顯著打包工具更新
Java 8 主要關注lambda表達式、Stream API等核心語言特性,在打包工具方面沒有顯著的更新。 JAR 包格式和打包流程與 Java 7 保持一致。
四、Java 9:模組化系統(Project Jigsaw)
Java 9 引入了模組化系統(Project Jigsaw),這對打包產生了深遠的影響。
-
模組定義檔(module-info.java):
引入了
module-info.java
文件,用於聲明模組的依賴關係、導出的包以及開放的包。 這是模組化打包的核心。 -
jlink 工具:
新增了
jlink
工具,用於創建自包含的、只包含運行應用程序所需的模組的運行時鏡像。 這極大地減少了應用程序的體積。 -
jdeps 工具增強:
jdeps
工具得到增強,可以分析模組之間的依賴關係。
架構:
graph LR A[Project Source] --> B(javac); B --> C([.class files]); C --> D{{module-info.java}}; D --> E((jlink tool)); E --> F[(Custom Runtime Image)];
範例:
module-info.java:
使用 jlink 創建自包含運行時鏡像:
五、Java 10 - Java 16:打包工具的持續改進
Java 10 到 Java 16 延續了 Java 9 模組化帶來的影響,並在打包工具方面進行了持續改進,主要集中在性能、對 Docker 容器的支援以及
jpackage
工具的發展。
-
應用程式類別資料共用 (AppCDS): AppCDS 允許在多個 JVM 實例之間共用類別元資料,從而加快啟動時間並減少記憶體佔用。 雖然 AppCDS 並非專門針對打包,但它與使用
jlink
建立的自訂執行時期映像配合使用,可顯著改善應用程式的效能。 -
Docker 容器感知: Java 虛擬機器能夠更好地檢測在 Docker 容器中運行的資源限制 (例如 CPU 和記憶體)。 這可確保 JVM 正確配置自身以獲得最佳效能,且避免超出容器的資源限制。
-
jpackage 工具 (在早期版本中為實驗性功能):
jpackage
工具在 Java 14 時納入作為孵化器模組,目的是為了建立平台專用的安裝程式套件 (例如.exe
、.dmg
、.deb
、.rpm
)。 它允許將 Java 應用程式打包成可在目標系統上輕鬆安裝和執行的應用程式。
工具:
-
jpackage
: 打包應用程式成安裝包。 -
jlink
: 創建自包含運行時映像。 -
jdeps
: 分析模組依賴關係。
六、Java 17:jpackage 工具成為正式功能
Java 17 最顯著的打包工具更新是
jpackage
工具正式成為標準功能,不再是孵化器模組。這表示
jpackage
工具已經足夠穩定和成熟,可以放心使用。
-
jpackage 工具正式化: 現在
jpackage
工具是 JDK 的一部分,不再需要額外安裝或啟用。 這簡化了使用jpackage
的過程,因為開發人員不必再處理孵化器模組。 -
更強大的平台支持: 提供了更廣泛的平台支持和配置選項,允許更精細地控制安裝包的生成過程。 開發人員現在可以更輕鬆地為各種作業系統和架構建立定制的安裝程式套件。
範例:使用 jpackage 建立完整範例
假設我們有一個簡單的 JavaFX 應用程式,想要將它打包成一個獨立的可執行檔。 該應用程式包含以下檔案:
-
src/module-info.java
(模組定義) -
src/com/example/myapp/Main.java
(主應用程式類別) -
src/com/example/myapp/App.java
(JavaFX 應用程式類別) -
resources/com/example/myapp/icon.png
(應用程式圖示)
本篇文章使用 Azul zulu JDK FX:
- 前往 Azul zulu 網站: https://www.azul.com/downloads/?package=jdk#zulu。
- 選擇 Java version(17+), operating system (Windows, macOS, or Linux), architecture (e.g., x64 or ARM) 與 Java Package 選擇 JDK FX。
- 將 ZIP 檔案解壓縮至指定的目錄,設定環境變數。

本篇文章在 Windows 系統上,使用 git bash 演示,產生 exe 檔案。需要下載 wixtoolset wix3 工具 ,將 wix314-binaries.zip 解縮至指定目錄後,設定環境變數。jpackage 預設情況下會使用 WiX (Windows Installer XML) 工具來建立 Windows 的安裝程式 (.exe 或 .msi)。 WiX 是一套用於建構 Windows 安裝套件的工具集。 light.exe 和 candle.exe 是 WiX 工具集中的兩個關鍵可執行檔。

原始碼目錄結構:
步驟 1: 建立模組定義檔 (
com.example.myapp/module-info.java
)
步驟 2: 建立 JavaFX 應用程式類別 (
com.example.myapp/com/example/myapp/App.java
)
步驟 3: 建立 FXML 佈局檔 (
com.example.myapp/app.fxml
)
步驟 4: 建立 Controller 類別 (
com.example.myapp/com/example/myapp/AppController.java
)
步驟 5: 編譯模組程式碼
執行結果出錯:
-
相關資源檔案 一般不會一起放入編譯後的目錄,這邊必須手動搬移 app.fxml 檔案。
-
執行結果:
-
步驟 6: 使用 jlink 建立自訂執行時期映像
執行結果:

步驟 7: 使用 jpackage 建立安裝程式
執行完畢後,
dist
目錄中會產生平台特定的安裝程式,例如
MyJavaApp-1.0.exe
(Windows) 或
MyJavaApp-1.0.dmg
(macOS)。
jpackage
命令參數說明:
-
--name <應用程式名稱>
:指定最終生成的應用程式的名稱。這個名稱會出現在安裝程式、桌面捷徑以及應用程式清單中。 -
--module <模組名>/<主類別名>
:指定應用程式的主模組和主類別。-
<模組名>
是包含應用程式入口點的模組名稱(即module-info.java
中聲明的module
名稱)。 -
<主類別名>
是應用程式的入口類別,通常包含public static void main(String[] args)
方法。 -
重要:
這個參數告訴
jpackage
從哪個模組和類別開始啟動你的應用程式。
-
-
--runtime-image <運行時映像路徑>
:指定由jlink
工具創建的自定義運行時映像的路徑。- 自定義運行時映像只包含應用程式運行所需的最小模組集合,可以顯著減小最終安裝包的大小。
-
如果沒有指定這個參數,
jpackage
會使用系統默認的 JDK,這可能導致安裝包體積過大。
-
--input <包含編譯後模組的目錄>
:指定包含編譯後的模組(即.class
文件)的目錄。這個目錄通常是編譯過程的輸出目錄。-
重要:
如果你的應用程式是模組化的(Java 9+),
jpackage
需要知道在哪裡可以找到編譯後的模組文件。
-
重要:
如果你的應用程式是模組化的(Java 9+),
-
--dest <輸出目錄>
:指定生成的安裝程式的輸出目錄。jpackage
會將最終的安裝包(例如.exe
、.dmg
、.deb
、.rpm
)放在這個目錄中。 -
--app-version <應用程式版本>
:指定應用程式的版本號。這個版本號會出現在應用程式的元數據中,並可以被安裝程式和作業系統讀取。 -
--description <應用程式描述>
:提供應用程式的簡短描述。這個描述會出現在安裝程式和應用程式資訊中。 -
--vendor <應用程式供應商>
:指定應用程式的供應商或開發者。這個資訊會出現在應用程式的元數據中。 -
--icon <應用程式圖示路徑>
:指定應用程式的圖示文件路徑。- 這個圖示會用於安裝程式、桌面捷徑以及應用程式清單中。
-
不同平台支持的圖示格式可能不同,例如 Windows 常用
.ico
,macOS 常用.icns
。
-
--java-options <JVM 選項>
:允許你傳遞額外的 JVM 選項給應用程式。-
例如,你可以使用
-Xmx
選項來設置應用程式的最大堆記憶體。
-
例如,你可以使用
-
--main-class <主類別>
:在某些情況下,如果--module
參數無法正確指定主類別,你可以使用--main-class
顯式指定主類別的完整名稱(包括包名)。 -
--type <安裝包類型>
:指定要生成的安裝包類型。-
常見的類型包括:
-
exe
(Windows) -
msi
(Windows Installer) -
dmg
(macOS) -
pkg
(macOS Installer Package) -
deb
(Debian/Ubuntu) -
rpm
(Red Hat/CentOS)
-
-
如果省略這個參數,
jpackage
會根據當前作業系統選擇默認的安裝包類型。
-
常見的類型包括:
-
--win-dir-chooser
(Windows):允許用戶在安裝過程中選擇安裝目錄。 -
--win-shortcut
(Windows):在安裝完成後,在桌面上創建一個應用程式的捷徑。
其他有用的選項:
-
--file-associations <文件關聯>
:允許你的應用程式處理特定類型的文件。 -
--license-file <許可證文件路徑>
:指定應用程式的許可證文件。 -
--copyright <版權聲明>
:指定應用程式的版權聲明。 -
--verbose
:啟用詳細輸出,可以幫助你診斷打包問題。
重要提示:
-
jpackage
工具的可用選項和行為可能因作業系統和 JDK 版本而異。建議查閱官方文檔以獲取最準確的資訊。 - 在創建安裝包之前,請確保你的應用程式已經過充分的測試,並且所有依賴項都已正確配置。
最終目錄結構:
步驟 9: 安裝程式執行結果






這個範例展示了如何使用
jpackage
工具建立一個完整的、獨立的 JavaFX 應用程式安裝程式。 這個方法可以確保應用程式可以在沒有安裝 JDK 的機器上執行,並且可以輕鬆地部署和分發。
七、總結
Java 7 至 17 的打包工具經歷了顯著的演進,旨在簡化部署、提升性能,並更好地適應現代應用程式開發需求。
-
Java 7: 引入了多版本 JAR 文件的概念和
MANIFEST.MF
的改進,為後續版本的多版本兼容打下基礎。 -
Java 9: 模組化系統 (Project Jigsaw) 帶來了革命性的變化,
module-info.java
定義模組依賴,jlink
工具創建自包含運行時映像,顯著減少應用程式體積,提升啟動速度。jdeps
工具則協助分析模組依賴關係。 -
Java 10-16: 持續優化,包括 AppCDS 加速啟動,提升 Docker 容器感知,以及
jpackage
工具的實驗性引入,為平台特定安裝包的創建奠定基礎。 -
Java 17:
jpackage
工具正式成為標準功能,提供更強大的平台支持和配置選項,簡化了將 Java 應用程式打包成獨立安裝包的流程。
關鍵演進與優勢:
-
體積優化:
jlink
創建自包含運行時映像,只包含應用程式所需的最小模組,顯著減少了應用程序的體積,更易於分發和部署。 - 性能提升: AppCDS 加速應用程式啟動速度,提高運行效率。
-
簡化部署:
jpackage
工具簡化了創建特定平台安裝包的過程,使得 Java 應用程式更易於安裝和執行,無需用戶手動安裝 JDK。 - 雲原生適應: 模組化系統和 Docker 容器感知,使 Java 應用程式更好地適應雲原生環境。
對開發者的意義:
理解這些演進對於 Java 開發者至關重要。 根據應用程式的需求和目標平台,選擇最佳的打包策略,能有效提升開發效率、簡化部署流程,並優化應用程式性能。從傳統的 JAR 包到現代化的模組化打包和平台特定安裝包,Java 的打包工具一直在不斷進化,為開發者提供更強大的支援。
沒有留言:
張貼留言