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