当前位置: 首页 > news >正文

Spring Boot 3.0系列【2】部署篇之使用GraalVM构建原生镜像

有道无术,术尚可求,有术无道,止于术。

本系列Spring Boot版本2.7.0

文章目录

    • 概述
    • JIT & AOT
      • JIT (动态编译)
      • AOT(静态编译)
    • GraalVM
      • 简介
      • 运行模式
    • Native Image(原生镜像)
      • Spring Native
      • 案例演示
        • 1. 安装 GraalVM Native-image C++环境
        • 2. 项目测试

概述

本篇介绍如何使用GraalVM构建原生镜像。

在开发Spring Boot 应用或者其他JAVA程序的过程中,启动慢、内存占用大是比较头疼的问题,往往需要更多的资源去部署,成本大幅提高。为了优化上述问题,常常使用优化程序、使用更小消耗的JVM、使用容器等措施。

现在有一个叫做Native Image(原生镜像)的技术,可以将JAVA应用的字节码直接编译为本地机器码,打包成本地可执行文件,运行应用时无需Java虚拟机进行动态编译,因此启动速度很快、内存消耗也很低。

JIT & AOT

在正式介绍Native Image之前,我们需要了解下JIT AOT的相关概念。

通常程序有两种运行方式:

  • 动态解释:解释执行,运行时翻译为机器码。
  • 静态编译:程序在执行前全部被翻译为机器码,可以直接运行二进制文件。

JIT (动态编译)

JITJust-in-time的缩写,一般称为即时编译动态编译Java源代码在运行的过程中,类加载器将需要运行的字节码处理并分配到内存中,然后JVM执行引擎需要调用解释器将字节码翻译为计算机能执行的机器码,最后执行机器指令。

需要解释执行势必会造成运行效率降低,为了提高执行速度,JAVA引入了 JIT 编译器。当某个方法或代码块运行特别频繁的时候,JVM会将其标注为热点代码, JIT 编译器会将热点代码编译成本地机器相关的机器码,优化后进行缓存,下次执行这些代码时,直接调用缓存中的机器码,无需重复解释,在一定程度上提高了执行速度。
在这里插入图片描述

AOT(静态编译)

JAVA一直在努力提高启动和运行时性能,希望其能够在更广泛的场景达到或接近本地语言的性能。虽然引入了JIT 编译器,但是需要花费较长时间才能热身完,而且有些Java方法还没法编译,性能方面也会下降。

AOTAhead-of-Time的缩写,一般称为静态编译。程序在执行前全部被翻译为机器码,可以直接运行二进制文件,比如C++就是使用静态编译。
在这里插入图片描述

JDK 9 中, AOT作为实验特性被引入,只支持 java.base 模块可以编译成AOT库,使用jaotc工具将Java类文件编译为本机代码,避免了 JIT 预热等各方面的开销。但是实际运行效果不尽人意,最终在JDK 16中被删除。

JDK 17中,也移除了实验性的AOTJIT,彻底拥抱GraalVM实现静态编译。

在当前微服务、云原生盛行的时代,JAVA 程序显得越来越臃肿,虽然使用AOT也有诸多缺点,比如打包时间长、舍弃平台无关性、反射、JNI、动态代理的分析能力有限。但是JAVA 必定会向AOT发展,否则在云原生时代,可以能被其他后起之秀慢慢蚕食市场。

GraalVM

简介

官网地址
GitHub地址

GraalVM是一个高性能跨语言虚拟机,其目的是提升Java和其他JVM语言编写程序的执行速度,同时也为JavaScriptPython和许多其他流行语言提供运行时环境。起始于 2011 年 Oracle 实验室的一个研究项目。
在这里插入图片描述GraalVM三大核心:

  • Java 虚拟机提供高性能的JIT编译器
  • 高性能的AOT编译器,提前将 Java 字节码编译为本机机器码。
  • 多种语言的支持,GraalVMTruffle语言实施框架可与 GraalVM 编译器协作,以卓越性能运行 JavaScript、Python、Ruby 以及 JVM 支持的其他语言。

GraalVM提供了两种运行Java应用程序的方法:

  • HotSpot JVM上使用实时JIT编译器
  • 使用AOTJava应用程序编译的本地可执行文件

社区版和企业版的一些区别

  • 社区版基于Open JDK,由社区组织维护
  • 社区版无定制的高级编译器优化
  • 在原生镜像中,社区版无压缩指针、配置文件引导优化、G1垃圾收集

在这里插入图片描述

GraalVM 的优点:

  • 帮助开发人员显著提升应用的性能效率,同时降低IT成本。

  • 构建现代 Java 应用,通过微服务和容器来满足云原生需求,微服务是执行单一功能的小型、独立微应用。在现实中,业务应用通常要使用数百项服务,每项服务都需要快速启动,以尽可能降低延迟和云使用成本。

  • 可以构建一个各种编程语言基于单一 JVM 运行的生态系统,提高开发效率。

GraalVM 的缺点:

  • 舍弃了 Java的平台无关性,编译为本地执行文件,不同操作系统的服务器,编译出来的文件不一样,比如 Windows 编译出来的文件,并不能在Linux 系统运行,也就让JAVA丢失了平台无关性。JAVA设计之初,一次编译、到处运行是其最重要的特性,但是现在容器技术的出现,该特性显得很牵强。
  • 反射机制、CGLIB动态代理这些和字节码打交道的机制,是在程序运行时动态调用,无法经过 AOT 编译成原生代码,构建时还需要提供各种配置文件去适配。
  • 目前该技术并未大面积使用,并不成熟。

运行模式

GraalVM提供了多种操作模式。

1、JVM运行时模式

HotSpot JVM上运行程序时,默认使用GraalVM编译器作为顶级JIT编译器。在运行时,应用程序在JVM上正常加载和执行。JVM将字节码传递给编译器,编译器将其编译为机器代码并将其返回给JVM

2、原生镜像

Native Image是一种创新技术,它将Java代码编译为独立的本地可执行文件或本地共享库。在构建本机可执行文件期间,处理的Java字节码包括所有应用程序类、依赖项、依赖于第三方的库以及所需的任何JDK类。生成的本地可执行文件特定于每个操作系统和机器体系结构,并不需要JVM

从当前GraalVM 22.1支持的功能图可以看出,Native Image可以在AMD6AArch64等服务器平台生成环境使用。
在这里插入图片描述

3、Java on Truffle

Java on Truffle 是一个 JVM 实现,它使用了 Truffle 多语言执行框架。提供了Java虚拟机所有的核心组件,实现了与Java运行时环境库相同的API,并重用GraalVM中的所有JAR和本机库。支持多语言互操作,例如,JavaScript 程序可以运行Ruby方法,无需制作副本就能共享数值。基于JVM运行时,Truffle 能够与GraalVM编译器协作,将受支持语言编译为本机机器码,从而优化性能。

Native Image(原生镜像)

了解了GraalVM之后,我们着重了解并使用Native Image技术将一个Spring Boot 3项目编译为一个可执行二进制文件。

Native Image:是一种将Java代码提前编译为二进制文件的技术,即本机可执行文件。本机可执行文件只包含运行时所需的代码,即应用程序类、标准库类、语言运行时以及来自JDK的静态链接本机代码

Native Image处理应用程序类和其他元数据,以创建特定操作系统和体系结构的二进制文件。首先,本地镜像工具对代码执行静态分析,以确定应用程序运行时可访问的类和方法。其次,它将类、方法和资源编译成二进制文件。整个过程被称为构建,以明确区分它与Java源代码到字节码的编译。
在这里插入图片描述

Native Image生成的可执行文件优点:

  • 使用虚拟机所需资源的一小部分,运行时更低的内存消耗
  • 以毫秒为单位启动
  • 立即提供最高性能,无需预热
  • 可以打包成轻量级容器映像,以实现快速高效的部署
  • 更不容易遭到破解、攻击

Spring Native

Spring NativeSpring 社区的一个开源框架,可以通过GraalVMSpring应用程序编译成原生镜像。

但是在GitHub可以看到,该项目已经关闭了:
在这里插入图片描述
官方推荐使用Spring Boot 3+GraalVM官方构建工具实现原生镜像构建,所以要注意Spring Native已经没必要再去研究及使用了

案例演示

官方环境要求文档

首先需要安装GraalVMnative-image组件,C++环境,最好不要在Windows 上使用,可以看到Spring Boot官网给出Windows 上使用的注意事项,就算按步骤做了~ 也有可能各种报错,所以切勿尝试😁😁😁
在这里插入图片描述

1. 安装 GraalVM Native-image C++环境

下载地址

选择系统对应的GraalVMNative-image安装包并下载,这里我使用的是Linux Ubuntu系统。
在这里插入图片描述
在这里插入图片描述
将文件上传到Linux 服务器:
在这里插入图片描述
执行以下命令安装GraalVM

# 解压tar -zxvf graalvm-ce-java17-linux-amd64-22.3.1.tar.gz 
# 添加环境变量
vim /etc/profile
# 添加内容
JAVA_HOME=/root/graalvm-ce-java17-22.3.1/
CLASSPATH=$JAVA_HOME/lib/
PATH=$PATH:$JAVA_HOME/bin
export PATH JAVA_HOME CLASSPATH
# 环境变量生效
source /etc/profile
# 查看
java -version

在这里插入图片描述
执行以下命令安装native-image

# 安装
gu -L install native-image-installable-svm-java17-linux-amd64-22.3.1.jar
# 查看
gu list

在这里插入图片描述
执行以下命令安装C++环境:

# Ubuntu 系统
sudo apt-get install build-essential libz-dev zlib1g-dev

2. 项目测试

准备一个Spring Boot 3.0.3项目:
在这里插入图片描述
添加GraalVM官方提供的构建插件:

    <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--原生镜像构建插件--><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.9.20</version><extensions>true</extensions><executions><execution><id>build-native</id><goals><goal>compile-no-fork</goal></goals><phase>package</phase></execution><execution><id>test-native</id><goals><goal>test</goal></goals><phase>test</phase></execution></executions><configuration><mainClass>com.pearl.nativeimagedemo.NativeImageDemoApplication</mainClass><imageName>native-image-demo</imageName><buildArgs><buildArg>--verbose</buildArg></buildArgs></configuration></plugin></plugins></build>

Linux服务器上安装Maven,将项目代码上传到服务器(内存至少6G,太少会卡住),执行mvn -Pnative -DskipTests native:compile编译,时间还是蛮久的,虽然这个项目比较空。

在这里插入图片描述
编译后在target下生成可执行文件,直接使用./native-image-demo就可运行,可以看到启动时间只有几十毫秒:
在这里插入图片描述

相关文章:

Spring Boot 3.0系列【2】部署篇之使用GraalVM构建原生镜像

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot版本2.7.0 文章目录概述JIT & AOTJIT &#xff08;动态编译&#xff09;AOT&#xff08;静态编译&#xff09;GraalVM简介运行模式Native Image&#xff08;原生镜像&#xff09;…...

复习知识点十之方法的重载

目录 方法的重载 练习1: 练习1: 数组遍历 练习2: 数组的最大值 练习3: 练习4: 复制数组 基本数据类型和引用数据类型 方法的重载 Java虚拟机会通过参数的不同来区分同名的方法 练习1: public class Test4 {public static void main(String[] args) {//调用方法 // …...

火爆全网的ChatGPT 和AI 可以为项目经理做什么?

作为一款人工智能聊天机器人&#xff0c;ChatGPT因其逼真和人性化的特性而风靡全球&#xff0c;无疑是当今技术的新流行。人工智能 (AI) 有可能彻底改变许多行业&#xff0c;包括项目管理&#xff0c;及时了解最新技术以及它如何影响你的工作至关重要。于是&#xff0c;我们与C…...

前端面试题 —— HTML

目录 一、src 和 href 的区别 二、对 HTML 语义化的理解 三、DOCTYPE(⽂档类型) 的作⽤ 四、script 标签中 defer 和 async 的区别 五、常⽤的 meta 标签有哪些&#xff1f; 六、HTML5 有哪些更新 八、行内元素有哪些&#xff1f;块级元素有哪些&#xff1f; 空(void)元素…...

同为(TOWE)电源线让家用电器随心放置

如今&#xff0c;随着科技水平的不断发展&#xff0c;人们工作、生活中越来越离不开各类电子设备和电器产品。当用电器数量多了以后&#xff0c;由于电器设备原有电线长度的限制&#xff0c;常常需要通过连接接线板来延长电器设备的电能传输线路。电源线虽然看着是一件不起眼的…...

2023上半年数学建模竞赛汇总(报名时间、比赛时间、难易程度、含金量、竞赛官网)

1、美国大学生数学建模竞赛等级&#xff1a;国家级是否可跨校&#xff1a;否竞赛开始时间&#xff1a;2月17日~2月21日综合难度&#xff1a;⭐⭐⭐⭐ 竞赛含金量&#xff1a;⭐⭐⭐⭐⭐竞赛官网&#xff1a;https://www.comap.com/2、MathorCup高校数学建模挑战赛---大数据竞赛…...

RK3568平台开发系列讲解(驱动基础篇)SMP(Symmetrical Multi-Processing)

🚀返回专栏总目录 文章目录 一、linux SMP 和 AMP二、linux SMP的启动流程三、CPU的描述:cpumask四、CPU之间的关系沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 SMP(Symmetrical Multi-Processing)。 一、linux SMP 和 AMP 目前支持多核处理器的实时操…...

HIVE --- zeppelin安装

目录 把zeppelin压缩包拷贝到虚拟机里面 解压 改名 修改配置文件 编辑zeppelin-site.xml—将配置文件的ip地址和端口号进行修改 编辑 zeppelin-env.sh—添加JDK和Hadoop环境 配置环境变量 刷新环境变量 拷贝Hive文件 拷贝外部文件 启动zeppelin 启动Hadoop&Hi…...

数据分析中的变量解释

1.数值变量Numerical Variables 数值型变量&#xff08;metric variable&#xff09;是说明事物数字特征的一个名称&#xff0c;其取值是数值型数据。如“产品产量”、“商品销售额”、“零件尺寸”、“年龄”、“时间”等都是数值型变量&#xff0c;这些变量可以取不同的数值…...

django-博客(一)

一、 1、环境&#xff1a;pycharm&#xff0c;python3.6&#xff0c;django3&#xff0c;mysql8.0 2、创建项目 3、把html和css样式那些导入到文件夹中&#xff0c;​​​​​​然后配置这些文件夹的路径&#xff0c;再添加首页视图。 改成反向解析 python manage.py runserv…...

Shell高级——Linux中的文件描述符

以下内容源于C语言中文网的学习与整理&#xff0c;非原创&#xff0c;如有侵权请告知删除。 前言 Linux中一切接文件&#xff0c;比如 C 源文件、视频文件、Shell脚本、可执行文件等&#xff0c;就连键盘、显示器、鼠标等硬件设备也都是文件。 一个 Linux 进程可以打开成百上…...

洗地机哪个品牌最好用?家用洗地机十大名牌

这几年清洁类的小家电非常热门&#xff0c;无线吸尘器、扫地机器人、扫拖一体机、洗地机和擦窗机器人层出不穷&#xff0c;各个品牌百花齐放。这些清洁电器&#xff0c;确实为家庭卫生清洁带来了很大的便捷。但要把这些产品一次性买齐是一笔不小的开销&#xff0c;而且需要收纳…...

java多线程(十)线程休眠

一、sleep()介绍 sleep() 定义在Thread.java中。 sleep() 的作用是让当前线程休眠&#xff0c;即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间&#xff0c;线程休眠的时间会大于/等于该休眠时间&#xff1b;在线程重新被唤醒时&#xff0c;它会由…...

Leetcode20. 有效的括号

一、题目描述&#xff1a; 给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确…...

Android 项目必备(四十三)-->Android 开发者的 new 电脑

前言 作为 Android 开发者&#xff0c;当你新入职一家公司&#xff0c;拿到新发的电脑&#xff0c;你会对电脑干点啥&#xff1f; 安装开发环境&#xff1f;装软件&#xff1f;你是否还会铺天盖地到处找之前电脑备份的东西&#xff1f;又或者还想不起来有什么上一台电脑好用的…...

如何水平和垂直居中元素

跳到主内容 我试图将我的选项卡内容垂直居中&#xff0c;但是当我添加 CSS 样式时display:inline-flex&#xff0c;水平文本对齐消失了。 如何为每个选项卡同时对齐文本 x 和 y&#xff1f; * { box-sizing: border-box; } #leftFrame {background-color: green;position: a…...

Rust泛型Generics

泛型 泛型&#xff08;Generics&#xff09;是一种程序设计风格&#xff0c;它允许程序员在强类型语言&#xff08;例如rust&#xff0c;c#&#xff0c;c&#xff09;中编写代码时使用通用类型。以rust为例&#xff0c;如果你想实现一个通用的add函数&#xff0c;让其在u8, i3…...

六、并发集合

文章目录并发集合ConcurrentHashMap存储结构存储操作put方法putVal方法-散列算法putVal方法-添加数据到数组&初始化数组putVal方法-添加数据到链表扩容操作treeifyBin方法触发扩容tryPreSize方法-针对putAll的初始化操作tryPreSize方法-计算扩容戳并且查看BUGtryPreSize方法…...

PHY调试经验

1. PHY调试过程 1.设备树中配置正确的PHY ADDR、PHY ID、clause 45或者22协议&#xff0c;PHY ADDR配置不正确会导致MDC/MDIO通信不正常或失败&#xff0c;PHY ID用于匹配PHY驱动程序。 2.通过MDC/MDIO读写PHY ID并对比datasheet中的PHY ID&#xff0c;确认MDC/MDIO通信是否正常…...

从Java培训班出来好找工作吗?

个人觉得这个问题要从两方面来看&#xff0c;首先是培训班的Java课程质量如何&#xff0c;是否贴合用人单位实际需求&#xff0c;学出来的技术能对口&#xff1b;其次是培训班是否保障就业&#xff0c;有就业机会渠道推荐&#xff0c;比如老学员内推、合作企业人才输送以及企业…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...

华为OD机考- 简单的自动曝光/平均像素

import java.util.Arrays; import java.util.Scanner;public class DemoTest4 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint[] arr Array…...

2025年全国I卷数学压轴题解答

第19题第3问: b b b 使得存在 t t t, 对于任意的 x x x, 5 cos ⁡ x − cos ⁡ ( 5 x t ) < b 5\cos x-\cos(5xt)<b 5cosx−cos(5xt)<b, 求 b b b 的最小值. 解: b b b 的最小值 b m i n min ⁡ t max ⁡ x g ( x , t ) b_{min}\min_{t} \max_{x} g(x,t) bmi…...