GraalVM & Spring Boot初體驗
前言
這兩天封在家里,一直在琢磨想去把這個博客項目改成微服務的形式。不過就目前而言我的服務器內(nèi)存放好幾個Java進程是吃不消的,原因在于一個獨立的JVM所占用的內(nèi)存資源太吃內(nèi)存。不過在云原生時代,使用容器化部署,每個服務單獨享受一整塊邏輯的內(nèi)存空間,實際上對Java是非常不利的。而且即便有的應用功能非常簡單,但是占用的內(nèi)存和功能完全不在一個量級,這可能也是Java常常為人詬病的一點。不過現(xiàn)在有了GraalVM,似乎一切都變得不一樣了。
配置
我下載的版本是GraalVM Community Edition 22.3.0,目前的最新版。大多數(shù)人其實更關心Spring項目如何整合這個JVM。根據(jù)官網(wǎng)配置,首先應該按照https://www.graalvm.org/22.3/docs/getting-started/macos/進行一些配置,接著在https://www.graalvm.org/22.3/reference-manual/native-image/下載GraalVM的一個組件Native Image:
gu install native-image
下載安裝完以后,其實配置就可以了。現(xiàn)在需要到Spring官網(wǎng)https://start.spring.io/去生成一個Demo,注意把GraalVM Native Support DEVELOPER TOOLS這個依賴給選上,最終我的依賴文件長這個樣子:
plugins {
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java'
id 'org.springframework.experimental.aot' version '0.12.1'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
maven { url 'https://repo.spring.io/release' }
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder:tiny'
environment = ['BP_NATIVE_IMAGE': 'true']
}
也不需要你去做什么,基本都自動生成了。我這里用的Spring Boot版本是2.7.5。
當GraalVM把項目構建完以后,在IDEA的Gradle插件的build下面選擇nativeCompile

然后開啟漫長的編譯過程:

編譯成功然后在build文件夾下就會有這么一個二進制可執(zhí)行文件demo:

這個文件可以直接雙擊啟動:

啟動用時52毫秒,非常的可以了。
而內(nèi)存占用呢:

不可能不心動。Java直接變成go了。
補充
如果需要在項目里使用動態(tài)代理,需要顯示指定需要代理的類,如:
@SpringBootApplication
@AotProxyHint(targetClass=com.example.demo.controller.TestController.class, proxyFeatures = ProxyBits.IS_STATIC)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
本質(zhì)是對這個切面的配置:
@Aspect
@Component
@Slf4j
public class TestAspect {
@Pointcut("execution(* com.example.demo.controller..*.*(..))")
public void pt() {}
@SneakyThrows
@Before("pt()")
public void before(JoinPoint jp) {
log.info("java");
}
}
不顯示聲明的話啟動會報錯。原因在于JVM的設計是一個開放的系統(tǒng),有些類是在運行時加載到虛擬機里的,這個就涉及了Java動態(tài)代理的原理。如果把程序編譯成二進制的文件脫離了JVM,就喪失了這種開放性,所以只能用這種沒有辦法的辦法將所有需要被代理的類枚舉式的聲明出來,在構建二進制文件的時候就把這些類提前的構建出來。
本文來自博客園,作者:imissinstagram,轉載請注明原文鏈接:http://www.rzrgm.cn/LostSecretGarden/p/16863026.html

浙公網(wǎng)安備 33010602011771號