使用 GraalVM 将纯 JavaFX 项目打包成 EXE
使用 GraalVM 將純 JavaFX 項目打包成 EXE
- GraalVM 的環境搭建
- 打包不含 FXML 的純 JavaFX 項目
- 打包含 FXML 的純 JavaFX 項目
- 測評
- 在 IntelliJ IDEA 中直接運行
- 生成 JAR 包后運行
- GraalVM 打包后運行
- GraalVM 與 Java 中其它打包成 EXE 的方法對比
- 總結
??GraalVM 可以使得 Java 應用可以脫離 JVM 來運行。換句話說,它可以使 Java 應用在沒有 Java 環境中運行。不過目前,這項技術還有很多的問題。由于 GraalVM 使用的是 AOT 技術,所以它不能直接用于打包含 Java 反射、動態代理的 Java 項目。一般來說,如果想對含 Java 反射、動態代理的 Java 項目使用 GraalVM 進行打包,必須提前向 GraalVM 提供一個列出了涉及 Java 反射、動態代理所有的類的 JSON 列表,否則,要么打包時會失敗,要么打包后的應用在運行時會失敗。
??另外,GraalVM 打包對內存的較高。在打包過程對內存的占用超 6 G 以上、CPU 占用 99% 是很常見的事情。此外,GraalVM 打包所用的時間也較長,可長達幾分鐘。正因為如此,在打包過程中,有些電腦管家類軟件還會報毒。
??JavaFX 支持使用 FXML 這種文本語言來創建組件,然而對于這種文本語言,Java 往往都中借助于反射技術來實現與其兼容。FXML 也不例外。之前,筆者已經編寫過使用 GraalVM 將基本的 Java 項目打包成 EXE 的教程,可見筆者的另一篇博客:
使用 GraalVM 將基本的 Java 項目打包成 EXE:
https://blog.csdn.net/wangpaiblog/article/details/122422987
??這次,筆者來示范一下如何使用 GraalVM 將純 JavaFX 項目打包成 EXE。純 JavaFX 項目指的是此 Java 項目沒有使用其它涉及反射、動態代理的 Java 框架或技術。
運行環境:
-
GraalVM Enterprise 21.3.0
-
Java 語言級別:17
-
JavaFX 17.0.1
-
Maven 3.8.3
-
IntelliJ IDEA 2021.2.2 (Ultimate Edition)
-
Windows 10 教育版 64位
GraalVM 的環境搭建
GraalVM 有兩種版本,Community 和 Enterprise。其中,前者對應于 OpenJDK,后者對應 Oracle JDK。需要根據自己的需要進行選擇,本文以 GraalVM Enterprise 21.3.0 為例。
GraalVM 版本選擇網址:https://www.graalvm.org/downloads/
下載 GraalVM Enterprise 21.3.0 需要進入 Oracle 官網,網址:https://www.oracle.com/downloads/graalvm-downloads.html?selected_tab=1
先下載 Oracle GraalVM Enterprise Edition Core。下載完成之后,應該會得到一個 zip 壓縮包。
再在剛才的頁面下載 Oracle GraalVM Enterprise Edition Native Image。這次得到的應該是一個 JAR 包。
將前面的 zip 壓縮包置入自己喜歡的文件夾下解壓,解壓得到的就是 GraalVM 程序文件。與安裝 JDK 時類似,將含 bin 的目錄作為 GraalVM 的安裝目錄。設環境變量如下:
-
變量名:ORACLE_GRAALVM_HOME
變量值:C:\Program Files\Java\graalvm-ee-java17-21.3.0
-
變量名:GRAALVM_HOME
變量值:%ORACLE_GRAALVM_HOME%
-
變量名:Path
變量值:%GRAALVM_HOME%\bin
如果上面的環境變量設置成功,在 CMD 的任意路徑中輸入以下命令應該能看到上面設置的路徑。
where javawhere gu
C:\>where java C:\Program Files\Java\graalvm-ee-java17-21.3.0\bin\java.exeC:\>where gu C:\Program Files\Java\graalvm-ee-java17-21.3.0\bin\gu.cmd
安裝 Native Image 包。Native Image 包就是前面下載的 JAR 包。輸入以下命令對 Native Image 進行本地安裝。
gu -L install Native Image 的 JAR 包路徑其中,Native Image 的 JAR 包路徑 要替換成實際的路徑。
GraalVM 的運行需要 Visual Studio 中的 MSVS 的支持,因此需要下載 Visual Studio。編寫本博客時,筆者下載的是 Microsoft Visual Studio Enterprise 2022 (64 位)。
Visual Studio 下載網址:https://visualstudio.microsoft.com/zh-hans/vs/
現在,Visual Studio 在官網上只會提供在線安裝包。下載完在線安裝包后,選擇安裝含 MSVS 的選項。
至此,GraalVM 的運行環境已經搭成。下面將開始使用 GraalVM 進行打包。
打包不含 FXML 的純 JavaFX 項目
為此,筆者編寫了一個簡易的不含 FXML 的純 JavaFX 項目。
【踩坑提醒】
-
對于 Java 8 以上的 JavaFX 項目,必須使用 Java 模塊系統才能對其進行 GraalVM 打包。出于本文的重點,這里不詳細介紹什么 Java 模塊系統以及它的語法。通常,構建 Java 模塊系統只需要在頂級目錄中添加一個模塊聲明文件 module-info.java。
-
項目的整個文件路徑中都不能含有中文,否則后面的 GraalVM 打包將失敗。
為了方便讀者自行快速實踐,項目源碼已上傳至 GitCode,位于 Git 分支 withoutfxml 中,可免費下載,鏈接:https://gitcode.net/wangpaiblog/20220209-purejavafx
這個項目所做的事情很簡單,模擬簡單的組件間的消息傳遞。如圖所示:
核心代碼如下:
package org.wangpai.demo.purejavafx;import java.io.IOException; import javafx.application.Application; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TextArea; import javafx.scene.layout.VBox; import javafx.stage.Stage;import static javafx.geometry.Pos.BOTTOM_RIGHT; import static javafx.geometry.Pos.CENTER;public class App extends Application {public static final long START_TIME = System.currentTimeMillis();@Overridepublic void start(Stage stage) throws IOException {var output = new TextArea();output.setPrefSize(200, 200);output.setEditable(false);output.setWrapText(true);var input = new TextArea();input.setPrefSize(200, 200);input.setWrapText(true);var send = new Button("發送(S)");send.setOnAction(event -> {var msg = input.getText();System.out.println(msg);output.setText(msg);input.requestFocus();input.clear();});var sendVbox = new VBox(send);sendVbox.setPrefSize(200, 0);sendVbox.setAlignment(BOTTOM_RIGHT);var vbox = new VBox(20, output, input, sendVbox);vbox.getStylesheets().add(App.class.getResource("/org/wangpai/demo/purejavafx/MainFace.css").toExternalForm());vbox.setAlignment(CENTER);vbox.setPrefSize(500, 500);vbox.setPadding(new Insets(20));Scene scene = new Scene(vbox, 500, 500);stage.setTitle("javafx without fxml");stage.setScene(scene);stage.show();output.setText("應用啟動用時:" + (System.currentTimeMillis() - START_TIME) / 1000.0 + "s");input.requestFocus();}public static void main(String[] args) {launch();} }因為本項目是使用 Maven 進行構建的,所以這里也使用 Maven 插件來進行 GraalVM 打包,這需要在 Maven 的 POM 文件中進行配置。關于 Maven 的安裝與插件,筆者在此之前也編寫一些博客,故此處不再對 Maven 做過多介紹。
這個插件是 Gluon 提供的,Gluon 現在實質上已經成為了 JavaFX 技術的主要提供商。
Gluon 官網:https://gluonhq.com/
JavaFX 的 GraalVM 打包 Maven 插件官方文檔網址:https://docs.gluonhq.com/#_gluonfx_plugin_for_maven
POM 的插件配置代碼模板如下:
<project...><build><plugins><plugin><groupId>com.gluonhq</groupId><artifactId>gluonfx-maven-plugin</artifactId><version>1.0.10</version><configuration><target>host</target><mainClass>入口類的包名.類名</mainClass></configuration></plugin></plugins></build> </project>注意:對于純 JavaFX 的 Java 模塊化項目,其入口類應該是一個繼承了 Application 的類。
如果需要在 JavaFX 中使用一些特殊的資源文件,這需要在此列出所有的這些文件。此插件打包時已經內置了如下類型的文件。
-
png, jpg, jpeg, gif, bmp, ttf, raw
-
xml, fxml, css, gls, json, dat,
-
license, frag, vert, obj
已經內置了類型的文件不需要自行列出(即上面列出的類型的文件不屬于上面所言的 特殊的資源文件)。更多的信息,可見:
https://docs.gluonhq.com/#_resourceslist
或
https://github.com/gluonhq/substrate/blob/master/src/main/java/com/gluonhq/substrate/target/AbstractTargetConfiguration.java#L70-L73
列出的方法是,在 <configuration/...> 中使用 <bundlesList/...>、<list/...>,然后在 <list/...> 中依次列出。如:
<project...><build><plugins><plugin><groupId>com.gluonhq</groupId><artifactId>gluonfx-maven-plugin</artifactId><version>1.0.10</version><configuration><target>host</target><mainClass>入口類的包名.類名</mainClass><bundlesList><list>文件路徑.文件名</list></bundlesList><reflectionList></configuration></plugin></plugins></build> </project>不過要注意,這個列出文件的時候,要像 Java 類一樣,使用點號來代替路徑分隔符,且不需要加上文件后綴。如:
<reflectionList><list>org.wangpai.demo.purejavafx.MainFace</list> </reflectionList>在項目目錄下的命令行中輸入如下命令使用 MSVS 的環境。這個命令是用于設置臨時設置與 MSVS 相關的環境變量,因此每次總是要輸。
vcvars64.bat 提供了 MSVS 的運行環境。雖然也可以通過設置 MSVS 的環境變量來代替,不過這樣要設置的環境變量會有很多。對于筆者的 Microsoft Visual Studio Enterprise 2022 (64 位),以上的命令為:
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"【踩坑提醒】
??需要進入 CMD 終端才能運行此命令。 IntelliJ IDEA 的終端默認使用 PowerShell 來運行命令,如果使用 IntelliJ IDEA 終端,需要將 IntelliJ IDEA 的終端設置成 CMD 模式(Command Prompt):
在項目目錄下的命令行中輸入如下命令進行 GraalVM 打包:(再次提醒:項目的整個文件路徑中都不能含有中文,否則 GraalVM 打包將失敗。)
mvn clean gluonfx:build打包完成之后,應該可以看到在項目路徑 \target\gluonfx\x86_64-windows\ 下的 EXE 文件。對于運行來說,就只有生成的 EXE 文件是核心文件,其它文件只是打包過程中生成的中間產物,都可以刪除。
打包完成之后,可以直接在操作系統或命令行中運行此 EXE 文件,也可以使用如下命令:
mvn gluonfx:nativerun如果選擇直接在操作系統或命令行中運行此 EXE 文件,則標準輸出流將不會定向到運行來源,這意味著將無法看到 System.out.println(...) 這之類代碼的輸出。
打包含 FXML 的純 JavaFX 項目
為此,筆者對上面的 JavaFX 項目作對應改編。改編之后的功能與改編之前完全一樣,這是為了方便之后的測評。
【踩坑提醒】
-
對于 Java 8 以上的 JavaFX 項目,必須使用 Java 模塊系統才能對其進行 GraalVM 打包。出于本文的重點,這里不詳細介紹什么 Java 模塊系統以及它的語法。通常,構建 Java 模塊系統只需要在頂級目錄中添加一個模塊聲明文件 module-info.java。
-
項目的整個文件路徑中都不能含有中文,否則后面的 GraalVM 打包將失敗。
為了方便讀者自行快速實踐,項目源碼已上傳至 GitCode,位于 Git 分支 withfxml 中,可免費下載,鏈接:https://gitcode.net/wangpaiblog/20220209-purejavafx
這個項目所做的事情很簡單,模擬簡單的組件間的消息傳遞。這和前面是一樣的,故此處不再贅述。
核心代碼如下:
package org.wangpai.demo.purejavafx;import java.io.IOException; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage;public class App extends Application {public static final long START_TIME = System.currentTimeMillis();@Overridepublic void start(Stage stage) throws IOException {FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource("MainFace.fxml"));Scene scene = new Scene(fxmlLoader.load(), 500, 500);stage.setTitle("javafx with fxml");stage.setScene(scene);stage.show();MainFace.afterUiShow("應用啟動用時:" + (System.currentTimeMillis() - START_TIME) / 1000.0 + "s");}public static void main(String[] args) {launch();} } <?xml version="1.0" encoding="UTF-8"?><?import javafx.geometry.Insets?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.TextArea?> <?import javafx.scene.layout.VBox?> <VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"prefHeight="500" prefWidth="500"fx:controller="org.wangpai.demo.purejavafx.MainFace"stylesheets="@MainFace.css"><padding><Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/></padding><TextArea prefHeight="200" prefWidth="200" editable="false" wrapText="true"fx:id="output"/><TextArea prefHeight="200" prefWidth="200" wrapText="true"fx:id="input"/><VBox alignment="BOTTOM_RIGHT" prefHeight="0" prefWidth="200"><Button text="發送(S)" onAction="#onActionSend"/></VBox> </VBox> package org.wangpai.demo.purejavafx;import java.net.URL; import java.util.ResourceBundle; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.TextArea;public class MainFace implements Initializable {private static MainFace mainFace;@FXMLprivate TextArea output;@FXMLprivate TextArea input;@FXMLpublic void onActionSend(ActionEvent event) {var msg = this.input.getText();System.out.println(msg);this.output.setText(msg);this.input.requestFocus();this.input.clear();}@Overridepublic void initialize(URL url, ResourceBundle resourceBundle) {mainFace = this;}public static void afterUiShow(String msg) {mainFace.input.requestFocus();mainFace.output.setText(msg);} }因為本項目是使用 Maven 進行構建的,所以這里也使用 Maven 插件來進行 GraalVM 打包,這需要在 Maven 的 POM 文件中進行配置。關于 Maven 的安裝與插件,筆者在此之前也編寫一些博客,故此處不再對 Maven 做過多介紹。
這個插件是 Gluon 提供的,Gluon 現在實質上已經成為了 JavaFX 技術的主要提供商。
Gluon 官網:https://gluonhq.com/
JavaFX 的 GraalVM 打包 Maven 插件官方文檔網址:https://docs.gluonhq.com/#_gluonfx_plugin_for_maven
POM 的插件配置代碼模板如下:
<project...><build><plugins><plugin><groupId>com.gluonhq</groupId><artifactId>gluonfx-maven-plugin</artifactId><version>1.0.10</version><configuration><target>host</target><mainClass>入口類的包名.類名</mainClass><reflectionList><list>JavaFX 控制器類的包名.類名</list></reflectionList></configuration></plugin></plugins></build> </project>注意:
-
對于純 JavaFX 的 Java 模塊化項目,其入口類應該是一個繼承了 Application 的類。
-
前面提到過,FXML 會導致 JavaFX 使用反射,為了讓 GraalVM 打包成功,這需要全部列出所有的 JavaFX 控制器類。
如果需要在 JavaFX 中使用一些特殊的資源文件,這需要在此列出所有的這些文件。此插件打包時已經內置了如下類型的文件。
-
png, jpg, jpeg, gif, bmp, ttf, raw
-
xml, fxml, css, gls, json, dat,
-
license, frag, vert, obj
已經內置了類型的文件不需要自行列出(即上面列出的類型的文件不屬于上面所言的 特殊的資源文件)。更多的信息,可見:
https://docs.gluonhq.com/#_resourceslist
或
https://github.com/gluonhq/substrate/blob/master/src/main/java/com/gluonhq/substrate/target/AbstractTargetConfiguration.java#L70-L73
列出的方法是,在 <configuration/...> 中使用 <bundlesList/...>、<list/...>,然后在 <list/...> 中依次列出。如:
<project...><build><plugins><plugin><groupId>com.gluonhq</groupId><artifactId>gluonfx-maven-plugin</artifactId><version>1.0.10</version><configuration><target>host</target><mainClass>入口類的包名.類名</mainClass><bundlesList><list>文件路徑.文件名</list></bundlesList><reflectionList></configuration></plugin></plugins></build> </project>不過要注意,這個列出文件的時候,要像 Java 類一樣,使用點號來代替路徑分隔符,且不需要加上文件后綴。如:
<reflectionList><list>org.wangpai.demo.purejavafx.MainFace</list> </reflectionList>在項目目錄下的命令行中輸入如下命令使用 MSVS 的環境。這個命令是用于設置臨時設置與 MSVS 相關的環境變量,因此每次總是要輸。
vcvars64.bat 提供了 MSVS 的運行環境。雖然也可以通過設置 MSVS 的環境變量來代替,不過這樣要設置的環境變量會有很多。對于筆者的 Microsoft Visual Studio Enterprise 2022 (64 位),以上的命令為:
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"【踩坑提醒】
??需要進入 CMD 終端才能運行此命令。 IntelliJ IDEA 的終端默認使用 PowerShell 來運行命令,如果使用 IntelliJ IDEA 終端,需要將 IntelliJ IDEA 的終端設置成 CMD 模式(Command Prompt):
在項目目錄下的命令行中輸入如下命令進行 GraalVM 打包:(再次提醒:項目的整個文件路徑中都不能含有中文,否則 GraalVM 打包將失敗。)
mvn clean gluonfx:build打包完成之后,應該可以看到在項目路徑 \target\gluonfx\x86_64-windows\ 下的 EXE 文件。對于運行來說,就只有生成的 EXE 文件是核心文件,其它文件只是打包過程中生成的中間產物,都可以刪除。
打包完成之后,可以直接在操作系統或命令行中運行此 EXE 文件,也可以使用如下命令:
mvn gluonfx:nativerun如果選擇直接在操作系統或命令行中運行此 EXE 文件,則標準輸出流將不會定向到運行來源,這意味著將無法看到 System.out.println(...) 這之類代碼的輸出。
測評
??前面已經介紹了 GraalVM 打包 JavaFX 項目的方法,不過 GraalVM 是否真的可以提高性能呢?如果可以,提高了多少呢?另外,JavaFX 對 FXML 使用了反射,這會不會大幅度影響性能呢?這種事情還是需要親身實踐一下才行。筆者在前面已經留了一手,在前面已經設置了同條件下無 FXML 與有 FXML 的對照組,用應用標題作區分,并在其中預留了應用啟動時間統計?,F在來看一下在 JavaFX 中使用和不使用 FXML 的啟動時間對比,以及使用 GraalVM 打包前后的啟動時間對比。因不同電腦的性能等差異,此結果僅供參考。
在 IntelliJ IDEA 中直接運行
??經過多次測試,本示例項目在 IntelliJ IDEA 中直接運行的啟動時間結果為:
-
無 FXML 版本:
-
啟動時間:約 0.7306 s
-
內存占用:120-130 MB 左右
-
-
有 FXML 版本:
-
啟動時間:約 0.7666 s
-
內存占用:120-130 MB 左右
-
??可以看出,在 IntelliJ IDEA 環境中,相對于有 FXML 版本,無 FXML 版本的啟動時間略小,減少了大約 5% 的啟動時間,這個減少的時間不是太明顯。另外,內存占用方面,無 FXML 版本也沒有明顯的優勢。
生成 JAR 包后運行
??為了模擬真實環境,這里還將每個項目打成 JAR 包作對比測試。打 JAR 包的插件使用的是 maven-shade-plugin,這個插件的具體配置,已在上面的源代碼中給出。關于這個插件的介紹與使用,可見筆者的另一篇博客:
Maven 配置文件 POM 的常用插件配置代碼:
https://blog.csdn.net/wangpaiblog/article/details/120735742
-
Oracle JDK 17 體積:288 MB
-
GraalVM Enterprise 21.3.0 體積:861 MB
-
無 FXML 版本:
-
打包后應用體積:8.84 MB
-
啟動時間:約 0.8662 s
-
內存占用:90-110 MB 左右
-
-
有 FXML 版本:
-
打包后應用體積:8.84 MB
-
啟動時間:約 0.9418 s
-
內存占用:90-110 MB 左右
-
??可以看出,在生成 JAR 包后運行,相對于有 FXML 版本,無 FXML 版本的啟動時間較小,減少了大約 8% 的啟動時間。但內存占用方面,無 FXML 版本沒有明顯的優勢。同時對比 IntelliJ IDEA 環境下的啟動時間,可以發現,IntelliJ IDEA 對 Java 項目的啟動進行了一些優化,同比減少了約 20% 的啟動時間,但代價是占用更多的內存,大約多占用了 15% 的內存。
GraalVM 打包后運行
-
無 FXML 版本:
-
打包耗時:約 2.1 min
-
打包過程中 CPU 最高平均占用:約 99.7%
-
打包過程中內存最高平均占用:約 7.3 G
-
打包后應用體積:69.9 MB
-
啟動時間:約 0.3076 s
-
內存占用: 75-85 MB 左右
-
-
有 FXML 版本:
-
打包耗時:約 2.03min
-
打包過程中 CPU 最高平均占用:約 99.4%
-
打包過程中內存最高平均占用:約 7.4 G
-
打包后應用體積:69.7 MB
-
啟動時間:約 0.3078 s
-
內存占用:75-85 MB 左右
-
??可以看出,GraalVM 打包過程中的消耗是比較大的,但有 FXML 版本與無 FXML 版本對 GraalVM 打包的影響幾乎為 0。無論是打包過程中,以及生成的 EXE 的運行,有 FXML 版本與無 FXML 版本之間都沒有明顯的數據上的差異。這說明,GraalVM 消除了 Java 反射的負面效果。這正是 AOT 技術的體現之一。
??對于啟動時間,使用 GraalVM 打包后減少了 60% 至 70%,這個減少的時間很可觀。對于內存占用,減少了 20% 左右的空間,但是占用的內存依然較大。對于應用體積,相對于原整個 JDK 來說,小了 75%,不過依然較大??偠灾?#xff0c;相對原始的 JAR 包運行,使用 GraalVM 打包后都有一定程度甚至很大幅度上的提高,但相對于 C 家族的 GUI 應用來說,即便是使用 GraalVM 打包,其應用體積、內存占用都沒有太大的競爭力。
GraalVM 與 Java 中其它打包成 EXE 的方法對比
??但是相對于 Java 中其它打包成 EXE 的方法,如果 GraalVM 打包成功,GraalVM 可以說是最優的方式。 Java 中其它打包成 EXE 的方式無非就如下幾種,或者是它們的變體。
-
方式 1:先生成 JAR,然后將運行 JAR 包的命令寫在一個腳本中,以后直接運行腳本即可。
但此方法本質上是先運行 Java 虛擬機,然后再用 Java 虛擬機加載運行 Java 代碼。Java 虛擬機會占用較高的內存,且在這種方式下,Java 項目無法擁有自己的父進程名,對外只顯示為 Java 虛擬機在運行。
-
方式 2:底層原理同方式 1,但將上面的腳本封裝成了一個 EXE。
這樣做能讓普通用戶不能直接操作底層的腳本命令,提高了一定的安全系數和用戶的友好度。除此之外,它跟方式 1 沒有太大的區別。但根據使用的封裝軟件不同,此 Java 項目可能擁有自己的進程名與圖標。
-
方式 3:底層原理同方式 2,但使用了一種 EXE 壓縮軟件將上面的 JAR 包與腳本封裝成了一個 EXE。
-
方式 4:底層原理同方式 3,但這種方式將 JRE 的相對路徑信息也儲存到了 EXE 中,這樣可以直接在此 EXE 附近放一個 JRE 文件,以后就可以在新電腦上無需先安裝 Java 即可馬上運行。
但這種方式需要向用戶提供 JRE,JRE 的體積一般都非常龐大。另外,這種方式本質上與前面幾種方式一樣,也是先運行 Java 虛擬機,然后再用 Java 虛擬機加載運行 Java 代碼。而 Java 虛擬機會占用較高的內存。
-
方式 5:前期步驟同方式 4,但額外借助了 Java 的一些內置工具命令精簡了 JRE 體積,使得打包之后應用體積大大減少。
但這種方式需要每次用人力去排除和篩選 JRE,然后編寫命令執行,無一般的規律可尋,且誤操作之后可能導致打包后運行失敗,這會增加人力時間成本。另外,這種方式只是減少了打包之后應用體積,而沒有減少運行內存。
-
方式 6:這種方式不同前面的這幾種方式。它直接使用 Java 內置的打包命令即可生成 EXE,而無需借助第三方制 EXE 的軟件。制好后可在新電腦上無需先安裝 Java 即可馬上運行。
但這種方式需要每次用人力進行文件布局和多次編寫命令執行。另外,這種方式打包后的應用,其運行時本質上還是依賴于 Java 虛擬機。
-
方式 7:底層原理同方式 6,但它被嵌入到 Java 的一種構建工具(如 Maven)的插件中,一定程序可以減少手動配置并適合離不開構建工具的項目。除此之外,它跟方式 6 沒有太大的區別。
-
GraalVM 方式:這種方式不同前面的這幾種方式。它生成的 EXE 的運行無需借助 Java 虛擬機,更無需先安裝 Java,且無論是應用體積還是運行內存在所有的打包方式是都是最少的。
但它不能直接支持含 Java 反射、動態代理(如 CGLIB)的 Java 項目,需要每次用人力統計所有使用過 Java 反射、動態代理的類,無一般的規律可尋。另外,在所有的打包方式中,GraalVM 打包的耗時最長,CPU、內存消耗都是最大的。
總結
??本文介紹了使用 GraalVM 成功將純 JavaFX 項目打包的方法,但 GraalVM 還有很長的一段路要走。對于很多 API,GraalVM 的支持都有限。如果在 Java 中使用了這些 API,GraalVM 的打包都會失敗,這無疑是給 Java 開發造成了很多限制。另外,GraalVM 對主流 Java 框架的支持很有限。在項目中使用的 Java 框架越多,GraalVM 的打包流程越復雜,需要注意的東西越多,打包成功率越低。
總結
以上是生活随笔為你收集整理的使用 GraalVM 将纯 JavaFX 项目打包成 EXE的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决JavaFX报错缺少 JavaFX
- 下一篇: 如何免安装服务器将 React 整合进