GraalVM是一种高性能的多语言虚拟机,用于运行以JavaScript等基于LLVM的各种语言编写的应用程序。对于Java应用也可作为通常JVM的替代,它更具有性能优势。GraalVM带来的一个有趣功能是它能够在创建JVM应用程序的提前编译(create ahead-of-time:AOT)本机镜像,从而保证了更快的启动时间和更低的内存占用。在本文中,我们将重点介绍如何创建Spring应用的本机二进制文件。

GraalVM Native Image 101

Java应用程序使用编译为字节码javac。在应用程序运行时,JVM将类文件加载到内存中,并分析程序的性能以获取热点。因此名称为“ HotSpot JVM ”。在刚刚在时间(JIT)编译器编译这些重复执行为本机代码应用程序的部分。 但是,JIT编译需要处理器时间和内存,这会影响应用程序的启动时间。

GraalVM原生本机镜像能提前将 JVM应用程序编译为当前机器的机器代码。它静态分析应用程序的字节码,找到所有可以访问的类和方法,并将它们编译为本地可执行文件。输出是特定于平台的可执行二进制文件。

例如,让我们从以下“ Hello World”程序构建原生镜像。

class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

首先,我们需要使用 javac:

$ javac HelloWorld.java

然后用native-image将这个类文件构建成可执行二进制文件。

$ native-image HelloWorld

要启动应用程序,只需:

$ ./helloworld
Hello World

本机镜像Java限制

GraalVM本机镜像静态分析是需要假设在封闭世界的前提下。它需要在镜像生成期间提前知道所有可能访问的字节码。因此,并非所有Java功能都受支持:例如,不支持动态类的加载/卸载。反射需要配置。CGLIB代理不适用,但是却支持JDK代理,还需要配置。此外,您还需要告诉本机镜像有关所有资源访问的信息。

配置以JSON文档的形式提供。例如,要配置反射,您可以创建以下文件,并使用-H:ReflectionConfigurationFiles命令行标志来指定命令的文件位置native-image。

[
{ "name":"java.lang.Object" },
{ "name":"org.apache.naming.factory.ResourceFactory", "methods" : [{"name": "<init>","parameterTypes":[]}] },
...
]

配置动态代理、JNI和资源访问时都需要创建类似的文件来。但是,手工完成所有这些工作需要很多工作,尤其是在我们处理大型应用程序时。幸运的是,有一个Java代理可以生成配置。它观察在JVM中运行的应用程序的行为,并生成生成本机映像所需的配置文件。

要获得完整的配置文件集,您需要在应用程序中使用所有代码路径。具有100%覆盖率的测试套件可以解决问题,但实际上,测试套件永远不会测试所有路径。因此,也可能需要手动修改这些配置文件。

Spring和GraalVM本机映像

从Spring Framework 5.1 开始,提供了对GraalVM本机映像的初始支持。 5.2开发周期的重点是改进集成和全面支持,而不需要额外的配置或变通办法,这是即将到来的Spring Framework 5.3发行版的主题之一。

在spring-graal-nativeGithub上库展示了如何从Spring启动应用程序构建本地镜像的例子。该项目实施了GraalFeature,在配置反射,代理等方面承担了繁重的工作。

看看Spring Boot带有Tomcat的Spring MVC示例:请记住,在撰写本文时,该示例期望您正在使用GraalVM 19.2.1,并且已native-image安装插件。在构建示例之前,我们需要编译Spring Graal Feature。github存储库的根目录具有一个bash脚本来执行此操作。

$ ./build-feature.sh

完成后,让我们转到Spring MVC example文件夹并执行compile.sh。它使用Maven构建Spring应用程序,然后生成GraalVM本机映像。该native-image命令随Spring Graal功能部件的位置以及各种配置文件一起提供。请注意,本机映像生成比常规Maven构建花费的时间要长得多。另外,该进程喜欢使用大量RAM。完成后,导航到该target文件夹并启动应用程序

$ ./springmvc-tomcat

. ____ _ __ _ _

/\ / ' __ _ () __ __ _ \ \ \

( ( )_
_ | '_ | '| | ' / ` | \ \ \

\/ )| |)| | | | | || (| | ) ) ) )

' |
| .__|| ||| |__, | / / / /

=|_|======|/=////

:: Spring Boot ::

...

INFO: Started TomcatApplication in 0.054 seconds (JVM running for 0.057)

注意0.054秒的快速启动时间。为了进行比较,在JVM中运行应用程序时,报告的启动时间为1.455秒。

总结

GraalVM本机映像使我们能够构建提前编译的JVM应用程序,这些应用程序启动速度非常快,并且使用的内存更少。这对于短暂的过程绝对是有用的,尤其是在无服务器的情况下(按毫秒计费)。

由于类路径扫描和自动配置,Spring Boot应用程序在启动期间非常占用CPU。当在共享主机上同时启动多个Spring Boot应用程序时,它们开始争夺CPU,启动时间增加。编排工具甚至可能终止进程,因为它们启动得不够快。快速启动的提前编译的Spring Boot应用程序可能是该问题的答案。

容器化的Spring Boot应用程序也会有所收获。由于本机二进制文件具有所需的一切,因此不再需要将JRE烘焙到容器中。我们可以构建较小的Docker映像。

一些以微服务为重点的框架已经利用了本机图像功能(例如Quarkus,Micronaut,Helidon)。尽管Spring Boot尚未完全支持本机映像生成,但我认为它将是该框架的重要补充。

原文地址:

https://blog.indrek.io/articles/running-spring-boot-apps-as-graalvm-native-images/

译文:在GraalVM中部署运行Spring Boot应用的更多相关文章

  1. 【docker-compose】使用docker-compose部署运行spring boot+mysql 【处理容器的时区问题】【详解】【福利:使用docker-compose构建 wordpress+mysql】

    ==================================================================================================== ...

  2. 运行 Spring Boot 应用的 3 种方式

    今天介绍 3 种运行 Spring Boot 应用的方式,看大家用过几种? 你所需具备的基础 什么是 Spring Boot? Spring Boot 核心配置文件详解 Spring Boot 开启的 ...

  3. 用 gradle 运行 spring boot 项目

    用 gradle 运行 spring boot 项目(网页中的第6章:https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/gradle-plug ...

  4. 如何在自定义端口上运行 Spring Boot 应用程序?

    为了在自定义端口上运行 Spring Boot 应用程序,您可以在 application.properties 中指定端口. server.port = 8090

  5. 使用IDEA 中 实现springboot 热部署 (spring boot devtools版)

    第一步:添加springboot的配置文件 首先我先贴出我的配置 添加依赖包 <!-- spring boot devtools 依赖包. --> <dependency> & ...

  6. 在Docker容器中运行Spring Boot的jar包 jar外的配置文件无法生效

    Spring Boot加载配置文件,默认会从几个固定位置搜索一下看看有没有配置文件 ——application.properties或者bootstrap.properties(如果你使用了sprin ...

  7. 如何运行Spring Boot项目

    背景 帮别人指导一个Spring Boot项目,它在本地把项目push到git服务器上,然后在部署的服务器上把代码pull下来(我猜应该是这个流程) 然后他问我这项目怎么运行? 我当时就懵了,因为我平 ...

  8. liunx从0开始部署vue+spring boot项目(包含:安装jdk、mysql、nginx)

    单纯记录,若有不合理不规范的地方请忽略. 0.配置JDK 0.下载liunx的jdk解压到/usr/local目录下. tar -xzvf jdk-8u291-linux-x64.tar.gz -C ...

  9. Spring Boot 框架学习 (一)配置并运行Spring Boot 框架

    下载开发工具: 下载完成打开以后,第一步检查环境 查看jdk是否配置: 接着一定要注意,maven通常情况下它是没有给你配置的,要自行配置: 右键新建: 然后依赖选择web.跟Mybatis就行了. ...

随机推荐

  1. stand up meeting 12-10

    今天项目会议正好利用了大家上课前的十五分钟,大家对项目进度和项目中所遇到的问题进行了沟通. 由于天赋同学与重阳小组沟通及时有效,在mapping的过程中直接将单词本中的type与我们单词挑战中的que ...

  2. SQL语句加锁分析

    背景 MySQL中SQL加锁的情况十分复杂,不同隔离级别.不同索引类型.索引是否命中的SQL加锁各不相同. 然而在分析死锁过程当中,熟知各种情况的SQL加锁是分析死锁的关键,因此需要将MySQL的各种 ...

  3. Os-hackNos-1靶机过关记录

    靶机地址:172.16.1.198(或112)  kali地址:172.16.1.108 1 信息收集 靶机界面如下 简单查看 OS:Ubuntu Web:Apache2.4.18 尝试端口扫描 开放 ...

  4. 痞子衡嵌入式:简析i.MXRT1170 Cortex-M4 L-MEM ECC功能特点、开启步骤、性能影响

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M4内核的L-MEM ECC功能. 本篇是 <简析i.MXRT1170 Cortex-M ...

  5. ubuntu16.04-交叉编译-SeetaFaceEngine-master

    0.前言 在要移植opecv和SeetaFaceEngine-master到ARM板子上运行的所有步骤之前,有几点需要注意的: 查看板子运行的Kernel版本 交叉编译工具链的gcc版本,关键就是工具 ...

  6. 用Java代码来校验QQ号

    校验qq号码: 1.要求必须是5-15位数字 2.0不能开头 分析: A:键盘录入一个qq号码 B:写一个功能实现校验 C:调用功能,输出结果. 代码实现:public class RegexDemo ...

  7. Java中Character类

    Character 类在对象中包装一个基本类型char的值此外,该类提供了几种方法,以确定字符的类别(小写字母,数字,等),并将字符从大写转小写,反之亦然. 构造方法: Character(char ...

  8. java中的Volatile关键字使用

    文章目录 什么时候使用volatile Happens-Before java中的Volatile关键字使用 在本文中,我们会介绍java中的一个关键字volatile. volatile的中文意思是 ...

  9. rabbitMQ本地安装(Mac版)

    一. 首先测试本机器是否安装wget命令 (可以通过wget www.baidu.com来测试,如果有响应则可直接进入步骤二,如果报错或者提示未安装wget则需要先安装wget) 1http://ft ...

  10. js 实现对象的混合与克隆效果,带完整版解析代码[helpers.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝无缝轮播图效果 对象混合 ...