備註:

開始使用 GraalVM 原生映像檔

簡介

這個實驗室會逐步引導您完成使用 GraalVM 原生映像檔建立雲端原生 Java 應用系統的流程。其目的是為開發者提供 Java 知識。

GraalVM 原生映像檔技術可將 Java 程式碼提前編譯為獨立的執行檔。在程式實際執行時,只有應用程式所需的程式碼會新增至執行檔中。

「原生影像」產生的執行檔有數個重要的優點,因此:

許多頂尖的微服務架構採用 GraalVM 原生映像檔,包括 Micronaut、Spring、Helidon 及 Quarkus,將提前編譯支援。

此外,原生映像檔還有 Maven 和 Gradle Plugin,讓您可以輕易地建立、測試 Java 應用程式,以及執行執行檔案。

注意:Oracle Cloud Infrastructure (OCI) 提供 GraalVM Enterprise,無須額外付費。

預估實驗室時間:45 分鐘

實驗室目標

在此實驗室中,您將會執行下列作業:

附註:如果您在實驗室中看到筆記型電腦圖示,就需要執行一些動作,例如輸入指令。請留意。

# This is where we you will need to do something

STEP 1:連線至遠端主機並檢查開發環境

您的開發環境是由遠端主機提供:配備 Oracle Linux 8、1 CPU 及 32GB 記憶體的 OCI 運算執行處理。
Luna Labs 桌上型電腦環境將在遠端主機就緒前顯示,最多可能需要兩分鐘的時間。

您可以透過在 Luna 桌面環境中執行設定命令檔,來連線至您的遠端主機。此命令檔可透過資源頁籤使用

  1. 在桌面上,按兩下 Luna-Lab.html 圖示。就會開啟此頁面,顯示實驗室特定的 Oracle Cloud Infrastructure 證明資料和資訊。

  2. 將會顯示資源頁籤。請注意,資源標題旁邊的主題將隨著佈建在茶科技雲中的運算執行處理而衍生。

  3. 佈建執行處理時,這最多可能需要 2 分鐘的時間,您將會在資源頁籤看到以下內容

    Luna 資源頁籤

  4. 從資源頁籤複製設定 VS 程式碼環境的組態命令檔。按一下檢視詳細資訊連結以顯示組態。複製此項目,如以下螢幕擷取畫面所示。

    複製組態指令碼

  5. 開啟終端機,如以下螢幕快照所示:

    開啟終端機

  6. 將組態代碼貼至終端機,該終端機會為您開啟 VS 代碼。

    貼上終端機 1

    貼上終端機 2

就已完成!恭喜,您現在已經順利連線到 Oracle Cloud 中的遠端主機!

有關開發環境的附註

您將使用 GraalVM Enterprise 21 作為這個實驗室的 Java 平台。GraalVM 是來自 Oracle,建置在信任和安全的 Oracle Java SE 上的高效能 JDK 發行軟體。

您的開發環境已預先配置這個實驗室所需的 GraalVM 和原生映像檔工具。

您可以在終端機中執行這些指令,即可輕鬆檢查:您可以在 VS Code 中建立終端機:Terminal > New Terminal

java -version

native-image --version

STEP 2:建置並執行示範應用程式

我們將使用示範應用程式來展示 GraalVM 原生映像檔:計算目前目錄與其子目錄內檔案數目的命令行 Java 應用程式。另外,應用程式還會計算檔案的總大小。

應用程式的來源代碼可在遠端主機上使用。

示範應用程式的注意事項

應用程式包含兩個 Java 檔案,可以在 src 目錄中找到:

可以手動建置應用程式,或使用 Maven 設定檔來建立應用程式。Maven 建置組態由 pom.xml 檔案提供。Maven 設定檔在單一 pom.xml 檔案中擁有不同的建置組態是一個好方法。如需詳細資訊,請參閱這個網頁中的 Maven 設定檔。

您可以瀏覽開啟 VS 代碼中的檔案。

這個實驗室會使用多個設定檔,而每個設定檔都有特定的用途:

  1. native :此設定檔會使用「GraalVM 原生映像檔」建立執行檔。
  2. java_agent :此設定檔會建立 Java 應用程式,其中的追蹤代理程式會追蹤應用程式中所有動態程式碼的用途,並將此資訊擷取至組態檔中。稍後詳細資訊。

您可以使用特定的 Maven 設定檔,將它作為參數傳送至 mvn 命令。設定檔的名稱會附加至 -P 旗標。您可以從 VS 程式碼中的終端機內執行下列指令。

下列範例顯示使用 Maven 建置時如何呼叫 native 設定檔:

mvn clean package -Pnative

現在,您已經對應用程式執行了什麼樣的基本瞭解了,以瞭解其運作方式。

  1. 在我們以 VS 代碼開啟的終端機內建立專案並執行專案:

    mvn clean package exec:exec
    

    上述指令會進行下列動作:

    1. 清除專案以移除任何產生的或已編譯的使用者自建物件。
    2. 建立一個包含應用程式的可執行 JAR 檔案。「原生映像檔」稍後將會使用此 JAR 檔案。
    3. 執行 exec Plugin 來執行應用程式。

    您應該會在產生的輸出中看到以下內容 (應用程式報告的檔案數目可能會有所不同):

    Counting directory: .
    Total: 15 files, total size = 511.9 KiB
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    

STEP 3:將「Java 應用程式」轉換成「執行檔」

接下來,您將使用「GraalVM 原生映像檔」建置應用程式的可執行版本。「GraalVM 原生映像檔」是一個預先時期的編譯技術,可將您的 Java 應用程式轉換為獨立的可執行檔案,而不需要 JDK 執行,可快速啟動且有效率。

遠端主機上已預先安裝「GraalVM 原生映像檔」。

  1. 若要開始,請檢查 target 目錄中有已編譯的 JAR 檔案:

    ls ./target
    drwxrwxr-x 1 krf krf    4096 Mar  4 11:12 archive-tmp
    drwxrwxr-x 1 krf krf    4096 Mar  4 11:12 classes
    drwxrwxr-x 1 krf krf    4096 Mar  4 11:12 generated-sources
    -rw-rw-r-- 1 krf krf  496273 Mar  4 11:38 graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar
    -rw-rw-r-- 1 krf krf    7894 Mar  4 11:38 graalvmnidemos-1.0-SNAPSHOT.jar
    drwxrwxr-x 1 krf krf    4096 Mar  4 11:12 maven-archiver
    drwxrwxr-x 1 krf krf    4096 Mar  4 11:12 maven-status
    

    您所需的檔案為 graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar

  2. 從命令行產生執行檔。您不需要使用 Maven Plugin 來使用 GraalVM 原生映像檔,但它可以提供協助。從專案的根目錄執行以下內容:demo

    native-image -jar ./target/graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar --no-fallback -H:Class=oracle.App -H:Name=file-count
    

    這會在目前的目錄中產生名為 file-count 的執行檔。

  3. 執行此執行檔,如下所示:

    ./file-count
    
  4. 現在就是應用程式。首先,先以執行檔形式執行,然後使用一般 java 指令執行:

    time ./file-count
    

    time java -cp ./target/graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar oracle.App
    

    native-image 指令產生的可執行檔案大幅比對應的 Java 應用程式更快。

深入了解如何建立可執行檔案。

您在步驟 2 中傳送到 native-image 命令的參數為何?

如需完整的文件,請參閱這個網頁

您也可以使用 GraalVM 原生影像 Maven 外掛程式執行 native-image 工具。專案 pom.xml (Maven 組態) 檔案包含下列程式碼片段,示範如何使用 Plugin 建立可執行檔:

<!-- Native Image -->
<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
    <version>${native.maven.plugin.version}</version>
    <extensions>true</extensions>
    <executions>
    <execution>
        <id>build-native</id>
        <goals>
        <goal>build</goal>
        </goals>
        <phase>package</phase>
    </execution>
    </executions>
    <configuration>
        <skip>false</skip>
        <imageName>${exe.file.name}</imageName>
        <mainClass>${app.main.class}</mainClass>
        <buildArgs>
            <buildArg>--no-fallback</buildArg>
            <buildArg>--report-unsupported-elements-at-runtime</buildArg>
        </buildArgs>
    </configuration>
</plugin>

原生影像 Maven 外掛程式會執行建置執行檔的重度。您可以使用 <skip>true</skip> 標記來將其停用。請注意,您可以透過 <buildArgs/> 標記將參數傳送至 native-image

如需「GraalVM 原生映像檔」外掛程式的完整文件,請參閱此處

若要使用 Maven 設定檔建立執行檔,請執行:

mvn clean package -Pnative

Maven 組建會將執行檔 file-count 放置在 target 目錄中。

您可以依照下列方式執行執行檔:

./target/file-count

STEP 4:使用反映 - 新增相依性至 Log4J

在此步驟中,您將建立可搭配 Java 動態功能使用的執行檔。

例如您想新增圖書館或一些程式碼到您的應用系統中,以反射這些反射。測試反射的好候選項目是 Log4J 記錄架構。它已在專案 pom.xml 檔案中新增為相依性:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

若要變更應用程式使其使用 log4j,請編輯 ListDir.java 檔案,然後取消註解幾行。

  1. 使用 VS 代碼開啟 ListDir.java 檔案

  2. 取消宣告 log4j 匯入的行註解,然後取消註釋下列行:

    //import org.apache.log4j.Logger;
    

    //final static Logger logger = Logger.getLogger(ListDir.class);
    

    /*
    // Add some logging
    if(logger.isDebugEnabled()){
        logger.debug("Processing : " + dirName);
    }
    */
    

    /*
    // Add some logging
    if(logger.isDebugEnabled()){
        logger.debug("Processing : " + f.getAbsolutePath());
    }
    */
    
  3. 儲存檔案

    現在您已將記錄加入至應用程式,就可以透過重建與執行來檢視變更的結果。

    mvn clean package exec:exec
    

    您看到的執行結果應該和先前執行的一樣,但是多了一些記錄。

  4. 接下來,請使用 Maven 設定檔來建立執行檔:

    mvn clean package -Pnative
    
  5. 執行您建立的執行檔,現在包含記錄日誌:

    ./target/file-count
    

    這樣會產生錯誤:

    Exception in thread "main" java.lang.NoClassDefFoundError
            at org.apache.log4j.Category.class$(Category.java:118)
            at org.apache.log4j.Category.<clinit>(Category.java:118)
            at java.lang.Class.ensureInitialized(DynamicHub.java:552)
            at oracle.ListDir.<clinit>(ListDir.java:75)
            at oracle.App.main(App.java:63)
    Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Category
            at java.lang.Class.forName(DynamicHub.java:1433)
            at java.lang.Class.forName(DynamicHub.java:1408)
            ... 5 more
    

    在這裡發生什麼事?

使用 Java 的動態功能

此異常狀況是因為新增 Log4J 程式庫,因為它仰賴反映。
native-image 工具會執行積極的靜態分析,以查看應用程式內使用的類別。對於任何未使用的類別,工具會假設不需要它們。這稱為「封閉世界」假設 - 建立可執行檔時需要載入的所有內容都必須是已知的。如果靜態分析找不到該分析,則執行檔就不會包含該分析。

反射是 Java 的核心功能,因此您可以使用反射充分利用 GraalVM 原生映像檔提供的速度?您需要一個讓 native-image 工具得知任何使用反射的方式。

幸運的是,native-image 工具可以在組態檔案中讀取,該檔案指定透過反映參照的所有類別。

您可以手動執行此操作,或是 GraalVM Java 執行時期隨附的 Java 追蹤代理程式即可為您執行這項作業。代理程式會產生 JSON 檔案,此檔案會記錄應用程式執行時可找到的所有反射執行處理、JNI、代理主機以及資源存取。

注意:執行追蹤代理程式時,必須執行應用程式中的所有程式碼路徑,以確保識別所有反射案例是很重要的。

如需追蹤代理程式的完整文件,請參閱這個網頁

STEP 5:使用追蹤代理程式

現在,當您執行應用程式時,請使用追蹤代理程式來產生反映組態。

  1. 使用追蹤代理程式執行應用程式:

    java -agentlib:native-image-agent=config-output-dir=./src/main/resources/META-INF/native-image -cp ./target/graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar oracle.App
    

    查看追蹤代理程式所建立的組態檔:

    ls -l src/main/resources/META-INF/native-image/
    

    您應該會在產生的輸出中看到以下內容:

    total 56
    -rw-r--r--  1 kfoster  staff     4B Dec  2 19:13 jni-config.json
    -rw-r--r--  1 kfoster  staff    86B Nov  9 20:46 native-image.properties
    -rw-r--r--  1 kfoster  staff    65B Dec  2 19:13 predefined-classes-config.json
    -rw-r--r--  1 kfoster  staff     4B Dec  2 19:13 proxy-config.json
    -rw-r--r--  1 kfoster  staff   521B Dec  2 19:13 reflect-config.json
    -rw-r--r--  1 kfoster  staff   101B Dec  2 19:13 resource-config.json
    -rw-r--r--  1 kfoster  staff     4B Dec  2 19:13 serialization-config.json
    

    注意:專案包含 Maven 設定檔,可供您執行這項作業。執行下列命令以使用追蹤代理程式:

    mvn clean package exec:exec -Pjava_agent
    
  2. 現在重新建立執行檔 。這次會套用追蹤代理程式所產生的組態檔:

    mvn package -Pnative
    
  3. 最後,執行產生的檔案:

    time ./target/file-count
    

    可執行檔的運作方式,並如預期般產生輸出的日誌訊息。

因為追蹤代理程式產生的檔案已記錄反映所參照的類別,所以這項操作是如此。native-image 工具現在知道它們在應用程式中使用,因此不會從產生的執行檔中排除。

-agentlib 參數的位置注意事項

請注意,代理程式參數必須位於任何 -jar-classpath 參數之前。您也應該指定要寫入檔案的目錄。建議的位置在 src/main/resources/META-INF/native-image 下。native-image 工具會自動擷取此位置中的檔案。

設定產生執行檔時的注意事項

您也可以使用 Java 特性檔 (預設為 src/main/resources/META-INF/native-image/native-image.properties) 將參數傳遞至 native-image 工具。demo 目錄中包含一個範例檔案,可讓您瞭解該檔案的運作方式。

結論 @ info:tooltip

在此實驗室中,您已嘗試數個 GraalVM 原生映像檔功能:

  1. 如何從 Java 命令行應用程式產生快速執行檔
  2. 如何使用 Maven 建立執行檔
  3. 如何使用追蹤代理程式將追蹤和記錄反映的程序自動化

利用 GraalVM 原生映像檔撰寫高效率、更安全且可即時調整的雲端原生 Java 應用系統!

深入瞭解

其他學習資源

探索 docs.oracle.com/learn 上的其他實驗室,或是存取更多免費學習內容至 Oracle Learning YouTube 通道。此外,瀏覽 education.oracle.com/learning-explorer 以成為 Oracle Learning Explorer。

如需產品文件,請瀏覽 Oracle Help Center