W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
GraalVM 是來自 Oracle 的新型通用虛擬機,它支持多語言運行時環(huán)境以及將 Java 應用程序編譯為本地機器代碼的能力。
任何 Micronaut 應用程序都可以使用 GraalVM JVM 運行,但是已向 Micronaut 添加了特殊支持以支持使用 GraalVM 的本機圖像工具運行 Micronaut 應用程序。
Micronaut 目前支持 GraalVM 版本 22.0.0.2,團隊正在改進每個新版本的支持。但是,如果您發(fā)現(xiàn)任何問題,請不要猶豫,報告問題。
Micronaut 的許多模塊和第三方庫已經(jīng)過驗證可以與 GraalVM 一起工作:HTTP 服務器、HTTP 客戶端、Function 支持、Micronaut Data JDBC 和 JPA、Service Discovery、RabbitMQ、Views、Security、Zipkin 等。對其他模塊的支持是不斷發(fā)展,并將隨著時間的推移而改進。
入門
僅在 Java 或 Kotlin 項目中支持使用 GraalVM 的原生圖像工具。 Groovy 嚴重依賴于 GraalVM 僅部分支持的反射。
要開始使用 GraalVM,請首先通過入門說明或使用 Sdkman! 安裝 GraalVM SDK。
作為 GraalVM 原生鏡像的微服務
開始使用 Micronaut 和 GraalVM
從 Micronaut 2.2 開始,任何 Micronaut 應用程序都可以使用 Micronaut Gradle 或 Maven 插件構建到原生鏡像中。首先,創(chuàng)建一個新的應用程序:
創(chuàng)建 GraalVM 原生微服務
$ mn create-app hello-world
您可以使用 --build maven 進行 Maven 構建。
使用 Docker 構建原生鏡像
要使用 Gradle 和 Docker 構建您的本機映像,請運行:
使用 Docker 和 Gradle 構建原生鏡像
$ ./gradlew dockerBuildNative
要使用 Maven 和 Docker 構建您的本機映像,請運行:
使用 Docker 和 Maven 構建原生鏡像
$ ./mvnw package -Dpackaging=docker-native
不使用 Docker 構建原生鏡像
要在不使用 Docker 的情況下構建本機映像,請通過入門說明或使用 Sdkman 安裝 GraalVM SDK?。?
使用 SDKman 安裝 GraalVM 22.0.0.2
$ sdk install java 22.0.0.2.r11-grl
$ sdk use java 22.0.0.2.r11-grl
本機圖像工具是從基礎 GraalVM 發(fā)行版中提取的,可作為插件使用。要安裝它,請運行:
安裝本機圖像工具
$ gu install native-image
現(xiàn)在,您可以通過運行 nativeCompile 任務來使用 Gradle 構建原生鏡像:
使用 Gradle 創(chuàng)建原生鏡像
$ ./gradlew nativeCompile
本機映像將構建在 build/native/nativeCompile 目錄中。
要使用 Maven 和 Micronaut Maven 插件創(chuàng)建原生圖像,請使用原生圖像打包格式:
使用 Maven 創(chuàng)建原生鏡像
$ ./mvnw package -Dpackaging=native-image
在目標目錄中構建本機圖像。
然后,您可以從構建它的目錄運行本機映像。
運行本機圖像
$ ./hello-world
了解 Micronaut 和 GraalVM
Micronaut 本身不依賴于反射或動態(tài)類加載,因此它會自動與 GraalVM 本機一起工作,但是 Micronaut 使用的某些第三方庫可能需要額外輸入有關反射使用的信息。
Micronaut 包含一個注解處理器,它有助于生成由原生圖像工具自動獲取的反射配置:
Gradle | Maven |
|
|
該處理器生成額外的類來實現(xiàn) GraalReflectionConfigurer 接口并以編程方式注冊反射配置。
例如下面的類:
package example;
import io.micronaut.core.annotation.ReflectiveAccess;
@ReflectiveAccess
class Test {
...
}
上面的示例導致 example.Test 的公共方法、聲明的字段和聲明的構造函數(shù)被注冊為反射訪問。
如果您有更高級的要求并且只希望包含某些字段或方法,請在任何構造函數(shù)、字段或方法上使用注釋以僅包含特定字段、構造函數(shù)或方法。
為反射訪問添加額外的類
為了通知 Micronaut 要包含在生成的反射配置中的其他類,可以使用許多注釋,包括:
@ReflectiveAccess 注釋通常用于特定類型、構造函數(shù)、方法或字段,而后兩者通常用于模塊或應用程序類以包含反射所需的類。例如,以下內(nèi)容來自帶有@TypeHint 的 Micronaut 的 Jackson 模塊:
使用@TypeHint 注解
@TypeHint(
value = { (1)
PropertyNamingStrategy.UpperCamelCaseStrategy.class,
ArrayList.class,
LinkedHashMap.class,
HashSet.class
},
accessType = TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS (2)
)
值成員指定哪些類需要反射。
accessType 成員指定是否只需要類加載訪問權限,或者是否需要對所有公共成員進行完全反射。
或者使用可重復的 @ReflectionConfig 注釋,并允許每種類型進行不同的配置:
使用@ReflectionConfig 注解
@ReflectionConfig(
type = PropertyNamingStrategy.UpperCamelCaseStrategy.class,
accessType = TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS
)
@ReflectionConfig(
type = ArrayList.class,
accessType = TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS
)
@ReflectionConfig(
type = LinkedHashMap.class,
accessType = TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS
)
@ReflectionConfig(
type = HashSet.class,
accessType = TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS
)
生成原生圖像
GraalVM 的 native-image 命令生成本機圖像。您可以手動使用此命令生成您的本機映像。例如:
native-image
命令
native-image --class-path build/libs/hello-world-0.1-all.jar (1)
構建映像后,使用本機映像名稱運行應用程序:
運行本機應用程序
$ ./hello-world
15:15:15.153 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 14ms. Server Running: http://localhost:8080
如您所見,本機圖像啟動在幾毫秒內(nèi)完成,并且內(nèi)存消耗不包括 JVM 的開銷(本機 Micronaut 應用程序僅使用 20mb 內(nèi)存運行)。
資源文件生成
從 Micronaut 3.0 開始,自動生成 resource-config.json 文件現(xiàn)在是 Gradle 和 Maven 插件的一部分。
GraalVM 和 Micronaut 常見問題解答
Micronaut 如何在 GraalVM 上運行?
Micronaut 具有依賴注入和不使用反射的面向方面編程運行時。這使得 Micronaut 應用程序更容易在 GraalVM 上運行,因為存在兼容性問題,尤其是在原生圖像中的反射方面。
如何讓使用 picocli 的 Micronaut 應用程序在 GraalVM 上運行?
Picocli 提供了一個 picocli-codegen 模塊,其中包含一個用于生成 GraalVM 反射配置文件的工具。該工具可以作為構建的一部分手動或自動運行。該模塊的自述文件包含使用說明和代碼片段,用于配置 Gradle 和 Maven 以在構建過程中自動生成 cli-reflect.json 文件。運行 native-image 工具時,將生成的文件添加到 -H:ReflectionConfigurationFiles 選項。
其他第三方庫呢?
Micronaut 不能保證第三方庫在 GraalVM SubstrateVM 上工作,這取決于每個單獨的庫來實現(xiàn)支持。
如果您收到如下錯誤:
Class myclass.Foo[] is instantiated reflectively but was never registered. Register the class by using org.graalvm.nativeimage.RuntimeReflection
您可能需要手動調(diào)整生成的 reflect.json 文件。對于常規(guī)類,您需要在數(shù)組中添加一個條目:
[
{
"name" : "myclass.Foo",
"allDeclaredConstructors" : true
},
...
]
對于數(shù)組,這必須使用 Java JVM 內(nèi)部數(shù)組表示。例如:
[
{
"name" : "[Lmyclass.Foo;",
"allDeclaredConstructors" : true
},
...
]
如果我想使用 -Xmx 設置堆的最大大小,但出現(xiàn) OutOfMemoryError 怎么辦?
如果您在用于構建本機映像的 Dockerfile 中設置最大堆大小,您可能會遇到如下運行時錯誤:
java.lang.OutOfMemoryError: Direct buffer memory
問題是 Netty 嘗試使用 io.netty.allocator.pageSize 和 io.netty.allocator.maxOrder 的默認設置為每個塊分配 16MB 的內(nèi)存:
int defaultChunkSize = DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER; // 8192 << 11 = 16MB
最簡單的解決方案是在 Dockerfile 的入口點中明確指定 io.netty.allocator.maxOrder。使用 -Xmx64m 的工作示例:
ENTRYPOINT ["/app/application", "-Xmx64m", "-Dio.netty.allocator.maxOrder=8"]
要更進一步,您還可以嘗試使用 io.netty.allocator.numHeapArenas 或 io.netty.allocator.numDirectArenas。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: