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. ASE team work proposal

    Hi,我们是Azure Wrapper,欢迎来到我们的blog~我们将在这里记录下ASE课程的滴滴点点,美妙的旅程就要开始啦! 以下是每位队员提交的关于ASE 团队项目的提议: 朱玉影: 随着信息时代 ...

  2. Vmware下安装Linux

    Linux系统 开源的操作系统.主要是应用在软件的服务器,性能比windows要好. Linux系统(ubuntu,centos,redhat,aix....) Linux主要是通过命令去操作计算机, ...

  3. [转]sql二次注入

    01 二次注入原理 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入.防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据 ...

  4. 编码理解的漫漫长路(Unicode、GBK、ISO)

    Ø 那么现在开始康康都有哪些编码方式  1.  ASCII

  5. 虎符ctf-MISC-奇怪的组织(看完官方题解,找到了)

    一道取证题,一整场比赛,基本就死磕了这一题 写的很乱,因为当时的思维就是那么乱,完全没有注意到出题人的提示, 还没做出来,没有找到关键key 那个人的real name 文档:虎符.note链接:ht ...

  6. 【山外笔记-云原生】《Docker+Kubernetes应用开发与快速上云》读书笔记-2020.04.25(六)

    书名:Docker+Kubernetes应用开发与快速上云 作者:李文强 出版社:机械工业出版社 出版时间:2020-01 ISBN:9787111643012 [山外笔记-云原生]<Docke ...

  7. Java中什么是构造方法

    this(...)本类的构造方法super(...)父类的构造方法构造方法:给对象的数据进行初始化格式:A:方法名与类名相同B:没有返回值类型,连void都没有C:没有具体的返回值注意事项:A:如果我 ...

  8. curl的$post传递多维数组

    php curl传数组的话只能传一维数组,如果想传多维数组:两个方法: 1.转换成json在传输 2. //通过curl模拟post的请求: function SendDataByCurl($url, ...

  9. 2019-2020-1 20199310《Linux内核原理与分析》第六周作业

    1.问题描述 在前面的文章中,学习了系统调用的相关理论知识,并使用库函数API和C代码中嵌入汇编代码两种方式使用getpid()系统调用.本文将内容围绕系统调用system_call的处理过程,在Me ...

  10. python学习13类2之封装

    '''''''''面向对象三大特性:封装,继承,多态1.封装: 类中以_或者__的属性,都是私有属性,禁止外部调用.'''class Student(object): def __init__(sel ...