原生映像檔建置配置

原生映像檔支援各種選項來配置 native-image 建置器。

目錄 #

嵌入設定檔 #

我們建議您透過將 *native-image.properties* 檔案嵌入專案 JAR 檔案中,為 native-image 建置器提供配置。native-image 建置器也會自動擷取在 *META-INF/native-image/* 目錄 (或其任何子目錄) 中提供的所有配置選項,並使用它來建構 native-image 命令列選項。

為避免專案的組成部分以重疊的配置進行建置,我們建議您在 *META-INF/native-image* 中使用子目錄:從多個 maven 專案建置的 JAR 檔案不會受到重疊 native-image 配置的影響。例如

  • foo.jar 的配置位於 META-INF/native-image/foo_groupID/foo_artifactID
  • bar.jar 的配置位於 META-INF/native-image/bar_groupID/bar_artifactID

包含 foobar 的 JAR 檔案接著將包含兩個配置,而不會發生衝突。因此,在 JAR 檔案中儲存配置資料的建議配置如下

META-INF/
└── native-image
    └── groupID
        └── artifactID
            └── native-image.properties

請注意,在 *native-image.properties* 檔案中使用 ${.} 會展開為包含該確切設定檔的資源位置。如果 *native-image.properties* 檔案參照其子目錄中的資源,這會很有用,例如,-H:ResourceConfigurationResources=${.}/custom_resources.json。務必使用採用資源的選項變體,也就是說,使用 -H:ResourceConfigurationResources 而不是 -H:ResourceConfigurationFiles。在此內容中運作的其他選項為

  • -H:DynamicProxyConfigurationResources
  • -H:JNIConfigurationResources
  • -H:ReflectionConfigurationResources
  • -H:ResourceConfigurationResources
  • -H:SerializationConfigurationResources

透過使用這種可組合的 *native-image.properties* 檔案,建置原生可執行檔不需要命令列上的任何其他選項。執行以下命令就足夠了

$JAVA_HOME/bin/native-image -jar target/<name>.jar

若要識別在建置原生可執行檔時套用的配置,請使用 native-image --verbose。這會顯示 native-image 從何處擷取配置,以建構原生映像檔建置器的最終複合配置命令列選項。

native-image --verbose -jar build/basic-app-0.1-all.jar
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/common/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/buffer/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/transport/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/handler/native-image.properties
Apply jar:file://~/build/basic-app-0.1-all.jar!/META-INF/native-image/io.netty/codec-http/native-image.properties
...
Executing [
    <composite configuration command line options for the image builder>
]

可以使用來自 *META-INF/native-image* 的配置的典型範例可在 原生映像檔配置範例 中找到。

設定檔格式 #

native-image.properties 檔案是 Java 屬性檔案,其中指定 native-image 的配置。支援下列屬性。

引數

如果您的專案需要自訂 native-image 命令列選項才能正確建置,請使用此屬性。例如,native-image-configure-examples/configure-at-runtime-example 在其 *native-image.properties* 檔案中包含 Args = --initialize-at-build-time=com.fasterxml.jackson.annotation.JsonProperty$Access,以確保類別 com.fasterxml.jackson.annotation.JsonProperty$Access 在可執行檔建置時初始化。

JavaArgs

有時可能需要為執行 native-image 建置器的 JVM 提供自訂選項。在此情況下,請使用 JavaArgs 屬性。

ImageName

此屬性會為可執行檔指定使用者定義的名稱。如果未使用 ImageName,則會自動選擇名稱:* native-image -jar <name.jar> 的預設可執行檔名稱為 <name> * native-image -cp ... fully.qualified.MainClass 的預設可執行檔名稱為 fully.qualified.mainclass

請注意,使用 ImageName 不會阻止您透過命令列覆寫名稱。例如,如果 foo.bar 包含 ImageName=foo_app:* native-image -jar foo.bar 會產生可執行檔 foo_app,但 * native-image -jar foo.bar application 會產生可執行檔 application

變更預設配置目錄 #

依預設,原生映像檔會將配置資訊儲存在使用者的主目錄中:* $HOME/.native-image/*。若要變更此預設值,請將環境變數 NATIVE_IMAGE_USER_HOME 設定為不同的位置。例如

export NATIVE_IMAGE_USER_HOME= $HOME/.local/share/native-image

引數評估順序 #

傳遞至 native-image 的選項會從左到右評估。這也擴展到透過 *META-INF/native-image* 目錄中的設定檔間接傳遞的選項。考量範例:其中有一個 JAR 檔案包含 *native-image.properties*,其中包含 Args = -H:Optimize=0。您可以使用 -H:Optimize=2 選項在 -cp <jar-file> 之後覆寫 JAR 檔案中包含的設定。

原生映像檔建置的記憶體配置 #

native-image 建置器在 JVM 上執行,並使用基礎平台的記憶體管理。適用於垃圾收集的常用 Java 命令列選項會套用至 native-image 建置器。

在建立原生可執行檔期間,會建立整個應用程式的表示法,以判斷哪些類別和方法會在執行階段使用。這是一個計算密集型程序,其使用下列記憶體使用率的預設值

-Xss10M \
-XX:MaxRAMPercentage=<percentage based on available memory> \
-XX:GCTimeRatio=19 \
-XX:+ExitOnOutOfMemoryError \

這些預設值可透過將 -J + <jvm memory option> 傳遞至 native-image 工具來變更。

-XX:MaxRAMPercentage 值會決定建置器的最大堆積大小,並根據系統的可用記憶體計算。預設最大值為 32GB,而且可以用例如 -J-XX:MaxRAMPercentage=90.0 代表 90% 的實體記憶體或 -Xmx4g 代表 4GB 來覆寫。-XX:GCTimeRatio=19 會將垃圾收集的總時間目標增加至 5%,這樣更能著重於輸送量,並減少峰值 RSS。建置程序也會在第一次 OutOfMemoryError (-XX:+ExitOnOutOfMemoryError) 時結束,以便在記憶體壓力很大的環境中提供更快速的回饋。

依預設,native-image 工具最多使用 32 個執行緒 (但不超過可用的處理器數目)。若要使用自訂值,請使用 --parallelism=... 選項。

如需其他適用於 native-image 工具的相關選項,請參閱命令 native-image --expert-options-all 的輸出。

指定在建置時需要定義的類型 #

完善的程式庫或應用程式在自行建置原生二進位檔時,應該處理 Java 類型的連結 (確保所有可達的 Java 類型在建置時完全定義)。預設行為是在執行階段發生連結錯誤時擲回這些錯誤。不過,您可以透過指定哪些類別必須在建置時完全連結來防止不必要的連結錯誤。若要執行此操作,請使用 --link-at-build-time 選項。如果在正確的環境中使用選項 (請參閱下方),您可以指定要在建置時連結的必要類別,而不需要明確列出類別和套件。其設計方式是讓程式庫只能配置自己的類別,以避免對其他程式庫產生任何副作用。您可以將選項傳遞至命令列上的 native-image 工具,將其嵌入模組路徑或類別路徑上的 *native-image.properties* 檔案中。

視選項的使用方式和位置而定,其行為會有所不同

  • 如果您使用沒有引數的 --link-at-build-time,則範圍中的所有類別都必須完全定義。如果在命令列上使用且沒有引數,則所有類別都將被視為「link-at-build-time」類別。如果在模組路徑上嵌入的 *native-image.properties* 檔案中使用且沒有引數,則模組的所有類別都將被視為「link-at-build-time」類別。如果您在類別路徑上嵌入的 *native-image.properties* 檔案中使用 --link-at-build-time,則會擲回下列錯誤
      Error: Using '--link-at-build-time' without args only allowed on module path. 'META-INF/native-image/org.mylibrary/native-image.properties' in 'file:///home/test/myapp/MyLibrary.jar' not part of module path.
    
  • 如果您將 --link-at-build-time 選項搭配引數使用,例如,--link-at-build-time=foo.bar.Foobar,demo.myLibrary.Name,...,則引數應該是完整的類別名稱或套件名稱。當在模組路徑或類別路徑上使用 (嵌入在 native-image.properties 檔案中) 時,只能指定在同一個 JAR 檔案中定義的類別和套件。在類別路徑上使用的程式庫的套件必須明確列出。為了讓這個程序變得簡單,請使用 @<prop-values-file> 語法在個別檔案中自動產生套件清單 (或類別清單)。

另一個方便的選項是 --link-at-build-time-paths,此選項允許透過其他方式指定哪些類別必須在建置時完全定義。這個變體需要與透過 -p (--module-path) 或 -cp (--class-path) 傳遞的引數類型相同的引數

--link-at-build-time-paths <class search path of directories and ZIP/JAR files>

會搜尋給定的項目,而且其中的所有類別都會註冊為 --link-at-build-time 類別。這個選項只允許在命令列上使用。

與我們聯繫