节省 95%的内存占用,减少 80%的启动耗时。


GraalVM 是一种高性能的虚拟机,它可以显著的提高程序的性能和运行效率,非常适合微服务。最近比较火的 Java 框架 Quarkus 默认支持 GraalVM

下图为 Quarkus 和传统框架(SpringBoot) 等对比图,更快的启动速度、更小的内存消耗、更短的服务响应

Spring Boot 2.4 开始逐步提供对 GraalVM 的支持,旨在提升上文所述的 启动、内存、响应的使用体验

安装 GraalVM

  • 目前官方社区版本最新为 20.3.0 ,是基于 OpenJDK 8u272 and 11.0.9 定制的,可以理解为 OpenJDK 的衍生版本



  • 官方推荐的是 SDKMAN 用于快速安装和切换不同版本 JDK 的工具 ,类似于 nodejs 的 nvm

使用类似命令即可完成指定版本安装和指定默认版本

sdk install java 11.0.9.hs-adpt
sdk default java 11.0.9.hs-adpt

不过安装过程中需要从国外下载相关资源 ,笔者在尝试后使用体验并不是很好,所有建议大家下载指定版本 GraalVM 安装即可(和 JDK 安装方式一样)。

  • 安装成功查看版本
⋊> ~ java -version                                                      11:30:34
openjdk version "11.0.9" 2020-10-20
OpenJDK Runtime Environment GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06)
OpenJDK 64-Bit Server VM GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06, mixed mode, sharing)

安装 native-image

native-image 是由 Oracle Labs 开发的一种 AOT 编译器,应用所需的 class 依赖项及 runtime 库打包编译生成一个单独可执行文件。具有高效的 startup 及较小的运行时内存开销的优势

但 GraalVM 并未内置只是提供 gu 安装工具,需要我们单独安装。

- 切换到 jdk 的安装目录
⋊> ~ cd $JAVA_HOME/bin/ - 使用gu命令安装
⋊> ./gu install native-image

初始化 Spring Boot 2.4 项目

  • Spring Initializr 创建 demo 项目
curl https://start.spring.io/starter.zip -d dependencies=web \
-d bootVersion=2.4.1 -o graal-demo.zip
  • 先看一下启动基准数据 , 单纯运行空项目 需要 1135 ms 秒
java -jar demo-0.0.1-SNAPSHOT.jar

engine: [Apache Tomcat/9.0.41]
2020-12-18 11:48:36.856 INFO 91457 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2020-12-18 11:48:36.856 INFO 91457 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1135 ms
  • 内存占用情况
ps aux | grep demo-0.0.1-SNAPSHOT.jar | grep -v grep | awk '{print $11 "\t" $6/1024"MB" }'
/usr/bin/java 480.965MB

支持 GraalVM

  • 增加相关依赖,涉及插件较多完整已上传 Gitee Gist
<!-- 新增的部分,注意需要增加  spring maven 仓库地址才能下载到-->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-graalvm-native</artifactId>
<version>0.8.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
</dependency> <!--需要添加 spring maven 仓库下载 spring-graalvm-native-->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
  • Main 方法修改,增加属性 proxyBeanMethods = false
@SpringBootApplication(proxyBeanMethods = false)

  • 使用 native-image 构建可执行文件
 mvn -Pnative package
#构建过程比较慢,日志如下
spring.factories files...
[com.example.demo.demoapplication:93430] classlist: 4,633.58 ms, 1.18 GB
_____ _ _ __ __ _
/ ___/ ____ _____ (_) ____ ____ _ / | / / ____ _ / /_ (_) _ __ ___
\__ \ / __ \ / ___/ / / / __ \ / __ `/ / |/ / / __ `/ / __/ / / | | / / / _ \
___/ / / /_/ / / / / / / / / / / /_/ / / /| / / /_/ / / /_ / / | |/ / / __/
/____/ / .___/ /_/ /_/ /_/ /_/ \__, / /_/ |_/ \__,_/ \__/ /_/ |___/ \___/
/_/ /____/ ...
[com.example.demo.demoapplication:93430] [total]: 202,974.38 ms, 4.23 GB
  • 编译结果

在 targe 目录生成 名称为 com.example.demo.demoapplication 可执行文件

  • 启动应用 这里执行的编译后的可执行文件而不是 jar
cd target

./com.example.demo.demoapplication
  • 启动时间 0.215 seconds
2020-12-18 12:30:40.625  INFO 94578 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.215 seconds (JVM running for 0.267)

  • 看一下内存占用 24.8203MB
ps aux | grep com.example.demo.demoapplication | grep -v grep | awk '{print $11 "\t" $6/1024"MB" }'

./com.example.demo.demoapplication	24.8203MB

数据对比

是否引入 GraalVM 内存占用 启动时间
480.965MB 1135 ms
24.8203MB 215 ms

>>> 源码 https://gitee.com/log4j/pig,欢迎署名转载 <<<

『Spring Boot 2.4新特性』减少95%内存占用的更多相关文章

  1. Spring Boot 2(一):Spring Boot 2.0新特性

    Spring Boot 2(一):Spring Boot 2.0新特性 Spring Boot依赖于Spring,而Spring Cloud又依赖于Spring Boot,因此Spring Boot2 ...

  2. Spring Boot 2.0 新特性和发展方向

    以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...

  3. 【2.0新特性】Spring Boot 2.0新特性

    以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...

  4. Spring Boot实践——Spring Boot 2.0 新特性和发展方向

    出自:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Jav ...

  5. Spring Boot 2.0 新特性

    这是一篇总结文章,主要收集 Spring Boot 2.0 相对于 Spring Boot 1.x 的新特性,本章节并不提供实践性质的源代码.在 Spring Boot 系列文章中会持续退出实践章节. ...

  6. Spring Boot 2.3 新特性优雅停机详解

    什么是优雅停机 先来一段简单的代码,如下: @RestController public class DemoController { @GetMapping("/demo") p ...

  7. 原创 Spring Boot 2.3 新特性分层JAR

    背景 在我们实际生产容器化部署过程中,往往会遇到 Docker 镜像很大,部署发布很慢的情况 影响 docker 镜像大小的因素,主要有以下三个方面: 基础镜像的大小 .尽量选择 aphine 作为基 ...

  8. 「Spring Boot 2.4 新特性」启动耗时详细监控

    背景 Spring Boot 项目随着项目开发过程中引入中间件数量的增加,启动耗时 逐渐增加. 笔者在 <Spring Boot 2.4.0 正式 GA,全面拥抱云原生>文章评论下发现了 ...

  9. Spring Boot 2.4 新特性,全新的Cron表达式处理机制

    说起 cron 表达式大家一定不陌生,我们常用来作为定时任务执行策略规则. 在 Spring Boot 框架中 cron 表达式主要配合 @Scheduled 注解在应用程序中使用. 在 Spring ...

随机推荐

  1. pytorch中修改后的模型如何加载预训练模型

    问题描述 简单来说,比如你要加载一个vgg16模型,但是你自己需要的网络结构并不是原本的vgg16网络,可能你删掉某些层,可能你改掉某些层,这时你去加载预训练模型,就会报错,错误原因就是你的模型和原本 ...

  2. List和String的非空判断

    1.如果想判断list是否为空,可以这么判断: if(null == list || list.size() ==0 ){ //为空的情况 }else{ //不为空的情况 } 2.list.isEmp ...

  3. html5的标签中,哪些是行内元素,哪些是块级元素。

    块级元素:块级大多为结构性标记 <address>...</adderss> <center>...</center>  地址文字 <h1> ...

  4. IntelliJ Idea tomcat 控制台输出乱码

    reference: https://blog.csdn.net/dandandeshangni/article/details/485442211. 在运行/调试 配置对话框的Startup/Con ...

  5. 使用lua-nginx模块实现请求解析与调度

    系统版本及需求: OS:CentOS 7.7.1908 OpenResty:1.15.8.2 目录 描述 安装配置 安装openresty 使用示例 HTTP请求复制 HTTP报文解析 总结 描述 l ...

  6. mysql从一个表提取数据更新另外一个表(修复表数据的不一致)

    目前碰到一个数据不一致的情况,有两张表,一张项目表,一张项目成员表,项目表有个字段是项目工作时间,是项目成员的工作时间汇总.是由于该了逻辑,所以要把数据改成一致. 项目表的大致结构如下. 表名:pro ...

  7. pytorch(06)autograd与逻辑回归

    autograd与逻辑回归 自动求导系统中两个常用的方法: torch.autograd.backward and torch.autograd.grad 演示理解一阶导数.二阶导数的求导过程 理解自 ...

  8. 用java输出"Hello,World!"

    Hello,World! 一般步骤 随便新建一个文件夹,存放代码 新建一个java文件 新建.txt文档 文件后缀名改为.java Hello.java [注意]系统可能没有显示后缀名,我们需要手动打 ...

  9. java 方法详解

    什么是方法 方法的定义和调用 值传递与引用传递 值传递:指的是在方法调用时,传递的是参数是按值的拷贝传递. 特点:传递的是值的拷贝,也就是传递后就互不相关了. 引用传递:指的是在方法调用时,传递的参数 ...

  10. 【深入理解Java虚拟机】垃圾回收

    引用计数算法 给对象加一个计数器,引用一次+1,引用时效就-1,当计数器=0时对象就不能再被使用: 实现简单,判定效率高:Java虚拟接没有使用,主要原因是很难解决对象之间循环引用问题: GC算法: ...