◀返回
使用 Native Image Gradle 外掛程式包含可達性中繼資料
您可以使用 Gradle 從 Java 應用程式建置原生可執行檔。為此,請使用 Native Build Tools 專案中提供的 GraalVM Native Image Gradle 外掛程式。
「真實世界」的 Java 應用程式可能需要一些 Java 反射物件,或呼叫一些原生程式碼,或存取類別路徑上的資源 - native-image
工具必須在建置時知道的動態功能,並以中繼資料的形式提供。(Native Image 在建置時動態載入類別,而不是在執行時載入。)
根據您的應用程式相依性,有三種方法可以使用 Native Image Gradle 外掛程式提供中繼資料
- 使用 GraalVM 可達性中繼資料儲存庫
- 使用追蹤代理程式
- 自動偵測(如果所需資源直接位於類別路徑上,則在 src/main/resources/ 目錄中)
本指南示範如何使用 GraalVM 可達性中繼資料儲存庫,以及 追蹤代理程式,建置原生可執行檔。本指南的目標是說明這兩種方法之間的差異,並示範使用可達性中繼資料如何簡化您的開發工作。
我們建議您按照說明逐步建立應用程式。或者,您可以直接前往完成的範例。
準備示範應用程式
注意:執行 Gradle 需要 17 到 20 之間的 Java 版本(請參閱 Gradle 相容性矩陣)。但是,如果您想使用 Java 21(或更高版本)執行您的應用程式,有一個解決方法:將
JAVA_HOME
設定為 17 到 20 之間的 Java 版本,並將GRAALVM_HOME
設定為適用於 JDK 21 的 GraalVM。有關更多詳細資訊,請參閱 Native Image Gradle 外掛程式文件。
先決條件
請確保您已安裝 GraalVM JDK。入門最簡單的方式是使用 SDKMAN!。如需其他安裝選項,請造訪下載區段。
-
在您最喜歡的 IDE 中使用 Gradle 建立一個新的 Java 專案,稱為「H2Example」,在
org.graalvm.example
套件中。 - 將預設的 app/ 目錄重新命名為 H2Example/,然後將預設檔案名稱 App.java 重新命名為 H2Example.java,並將其內容取代為以下內容
package org.graalvm.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; public class H2Example { public static final String JDBC_CONNECTION_URL = "jdbc:h2:./data/test"; public static void main(String[] args) throws Exception { // Cleanup withConnection(JDBC_CONNECTION_URL, connection -> { connection.prepareStatement("DROP TABLE IF EXISTS customers").execute(); connection.commit(); }); Set<String> customers = Set.of("Lord Archimonde", "Arthur", "Gilbert", "Grug"); System.out.println("=== Inserting the following customers in the database: "); printCustomers(customers); // Insert data withConnection(JDBC_CONNECTION_URL, connection -> { connection.prepareStatement("CREATE TABLE customers(id INTEGER AUTO_INCREMENT, name VARCHAR)").execute(); PreparedStatement statement = connection.prepareStatement("INSERT INTO customers(name) VALUES (?)"); for (String customer : customers) { statement.setString(1, customer); statement.executeUpdate(); } connection.commit(); }); System.out.println(""); System.out.println("=== Reading customers from the database."); System.out.println(""); Set<String> savedCustomers = new HashSet<>(); // Read data withConnection(JDBC_CONNECTION_URL, connection -> { try (ResultSet resultSet = connection.prepareStatement("SELECT * FROM customers").executeQuery()) { while (resultSet.next()) { savedCustomers.add(resultSet.getObject(2, String.class)); } } }); System.out.println("=== Customers in the database: "); printCustomers(savedCustomers); } private static void printCustomers(Set<String> customers) { List<String> customerList = new ArrayList<>(customers); customerList.sort(Comparator.naturalOrder()); int i = 0; for (String customer : customerList) { System.out.println((i + 1) + ". " + customer); i++; } } private static void withConnection(String url, ConnectionCallback callback) throws SQLException { try (Connection connection = DriverManager.getConnection(url)) { connection.setAutoCommit(false); callback.run(connection); } } private interface ConnectionCallback { void run(Connection connection) throws SQLException; } }
-
刪除 H2Example/src/test/java/ 目錄(如果存在)。
- 開啟 Gradle 設定檔 build.gradle,並將其內容取代為以下內容
plugins { id 'application' // 1. Native Image Gradle plugin id 'org.graalvm.buildtools.native' version '0.10.1' } repositories { mavenCentral() } // 2. Application main class application { mainClass.set('org.graalvm.example.H2Example') } dependencies { // 3. H2 Database dependency implementation("com.h2database:h2:2.2.220") } // 4. Native Image build configuration graalvmNative { agent { defaultMode = "standard" } binaries { main { imageName.set('h2example') buildArgs.add("-Ob") } } }
1 啟用 Native Image Gradle 外掛程式。此外掛程式會探索哪些 JAR 檔案需要傳遞給
native-image
,以及可執行檔的主要類別應該是什麼。2 明確指定應用程式的主要類別。
3 加入 H2 資料庫 的相依性,這是 Java 的開放原始碼 SQL 資料庫。應用程式透過 JDBC 驅動程式與此資料庫互動。
4 您可以在
graalvmNative
外掛程式組態中將參數傳遞給native-image
工具。在個別的buildArgs
中,您可以完全以從命令列執行的方式傳遞參數。啟用快速建置模式(僅建議在開發期間使用)的-Ob
選項即為一個範例。imageName.set()
用於指定產生的二進位檔的名稱。從外掛程式的文件中瞭解其他組態選項。 - 此外掛程式尚未在 Gradle 外掛程式入口網站上提供,因此請宣告一個額外的外掛程式儲存庫。開啟 settings.gradle 檔案,並將預設內容取代為以下內容
pluginManagement { repositories { mavenCentral() gradlePluginPortal() } } rootProject.name = 'H2Example' include('H2Example')
請注意,
pluginManagement {}
區塊必須出現在檔案中的任何其他陳述式之前。 - (選用)建置應用程式。從儲存庫的根目錄中,執行以下命令
./gradlew run
這會產生一個「可執行」JAR 檔案,其中包含應用程式的所有相依性,以及一個正確設定的 MANIFEST 檔案。
使用 GraalVM 可達性中繼資料儲存庫建置原生可執行檔
Native Image Gradle 外掛程式提供對 GraalVM 可達性中繼資料儲存庫的支援。此儲存庫為預設情況下不支援 GraalVM Native Image 的程式庫提供 GraalVM 組態。其中之一是此應用程式所依賴的 H2 資料庫。必須明確啟用支援。
- 開啟 build.gradle 檔案,並在
graalvmNative
外掛程式組態中啟用 GraalVM 可達性中繼資料儲存庫metadataRepository { enabled = true }
整個組態區塊應如下所示
graalvmNative { agent { defaultMode = "standard" } binaries { main { imageName.set('h2example') buildArgs.add("-Ob") } } metadataRepository { enabled = true } }
此外掛程式會自動從儲存庫下載中繼資料。
- 現在使用中繼資料建置原生可執行檔
./gradlew nativeRun
這會在 build/native/nativeCompile/ 目錄中產生一個名為
h2example
的平台原生可執行檔。此命令也會從該原生可執行檔執行應用程式。
使用 GraalVM 可達性中繼資料儲存庫增強了對取決於第三方程式庫的 Java 應用程式使用 Native Image 的可用性。
使用追蹤代理程式建置原生可執行檔
為 native-image
提供中繼資料組態的第二種方法是在編譯時注入 追蹤代理程式(以下稱為代理程式)。
代理程式可以在三種模式下執行
- 標準:無條件收集中繼資料。如果您要建置原生可執行檔,建議使用此模式。
- 條件式:有條件地收集中繼資料。如果您要為用於進一步使用的原生共用程式庫建立條件式中繼資料,建議使用此模式。
- 直接:僅限進階使用者使用。此模式允許直接控制傳遞給代理程式的命令列。
您可以透過在命令列上傳遞選項或在 build.gradle 檔案中組態代理程式。請參閱下文如何使用追蹤代理程式收集中繼資料,並建置套用所提供組態的原生可執行檔。
- 開啟 build.gradle 檔案,並查看
graalvmNative
外掛程式組態中指定的代理程式模式graalvmNative { agent { defaultMode = "standard" } ... }
如果您偏好使用命令列選項,則是
-Pagent=standard
。 - 現在在 JVM 上使用代理程式執行您的應用程式。若要使用 Native Image Gradle 外掛程式啟用代理程式,請將
-Pagent
選項傳遞給任何擴充JavaForkOptions
的 Gradle 工作(例如,test
或run
)./gradlew -Pagent run
代理程式會擷取並記錄對 H2 資料庫的呼叫,以及測試執行期間遇到的所有動態功能,並將其記錄到多個 *-config.json 檔案中。
- 收集完中繼資料後,使用
metadataCopy
工作將其複製到專案的 /META-INF/native-image/ 目錄中./gradlew metadataCopy --task run --dir src/main/resources/META-INF/native-image
輸出目錄不是必要的,但建議使用 /resources/META-INF/native-image/。
native-image
工具會自動從該位置挑選中繼資料。如需有關如何自動為您的應用程式收集中繼資料的詳細資訊,請參閱自動收集中繼資料。 - 使用代理程式收集的組態建置原生可執行檔
./gradlew nativeCompile
名為 h2example 的原生可執行檔會在 build/native/nativeCompile 目錄中建立。
- 從原生可執行檔執行應用程式
./build/native/nativeCompile/h2example
- (選用)若要清理專案,請執行
./gradlew clean
,並刪除 META-INF 目錄及其內容。
摘要
本指南示範如何使用 GraalVM 可達性中繼資料儲存庫和追蹤代理程式建置原生可執行檔。目標是顯示差異,並證明使用可達性中繼資料如何簡化工作。
請注意,如果您的應用程式在執行階段不呼叫任何動態功能,則無需啟用 GraalVM 可達性中繼資料儲存庫。在這種情況下,您的工作流程將會是
./gradlew nativeRun