前言

这两天封在家里,一直在琢磨想去把这个博客项目改成微服务的形式。不过就目前而言我的服务器内存放好几个Java进程是吃不消的,原因在于一个独立的JVM所占用的内存资源太吃内存。不过在云原生时代,使用容器化部署,每个服务单独享受一整块逻辑的内存空间,实际上对Java是非常不利的。而且即便有的应用功能非常简单,但是占用的内存和功能完全不在一个量级,这可能也是Java常常为人诟病的一点。不过现在有了GraalVM,似乎一切都变得不一样了。

配置

我下载的版本是GraalVM Community Edition 22.3.0,目前的最新版。大多数人其实更关心Spring项目如何整合这个JVM。根据官网配置,首先应该按照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

下载安装完以后,其实配置就可以了。现在需要到Spring官网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文件夹下就会有这么一个二进制可执行文件demo:

这个文件可以直接双击启动:

启动用时52毫秒,非常的可以了。

而内存占用呢:

不可能不心动。Java直接变成go了。

补充

如果需要在项目里使用动态代理,需要显示指定需要代理的类,如:

@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);
}
}

本质是对这个切面的配置:

@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的设计是一个开放的系统,有些类是在运行时加载到虚拟机里的,这个就涉及了Java动态代理的原理。如果把程序编译成二进制的文件脱离了JVM,就丧失了这种开放性,所以只能用这种没有办法的办法将所有需要被代理的类枚举式的声明出来,在构建二进制文件的时候就把这些类提前的构建出来。

最新文章

  1. selenium截图对比校验方法
  2. VS2010中的查找和替换中正则的使用
  3. 浅谈设计模式--装饰者模式(Decorator Pattern)
  4. 序列化.to_sym
  5. JAVA fundamentals of exception handling mechanism
  6. 用“逐步排除”的方法定位Java服务线上“系统性”故障(转)
  7. Windows SDK 实现不规则窗口介绍
  8. VBScript连接数据库
  9. AOJ 0558 广度优先搜索
  10. for循环语句
  11. Centos 7.3 编译 & 安装 & 测试 facebook faiss
  12. 从Excel导数据到MySQL速度优化
  13. typeof获取变量的数据类型 javascript
  14. JavaScript -- JSON.parse 函数 和 JSON.stringify 函数
  15. Git使用详细教程(1):工作区、暂存区、本地仓库、远程仓库
  16. 爬取小说 spider
  17. 基于NEO的私链(Private Blockchain)
  18. CSRF重放共计详解
  19. 百度echarts极速入门
  20. Linux C 数据结构->双向链表(阴阳在六,何以言九~)

热门文章

  1. 用requests-html和SelectorGadget轻松精准抓取网页数据
  2. 第七章用Python实现对Excel文件中的数据进行md5加密
  3. java泛型元组
  4. 四、vMotion虚拟机迁移
  5. php集成环境包PhpStudy及部署网站
  6. mysql报错:MySQL server has gone away
  7. ssh 远程报错 Permission denied, please try again.(密码输入正确也无法登录)
  8. List集合增删元素时,UnsupportedOperationException报错问题
  9. Redis缓存中的数据和数据库不一致
  10. STM32F0 LL库IIC第二地址配置错误