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

Spring Boot应用使用GraalVM本地编译相关配置

1. 介绍

Java应用程序可以通过Graalvm Native Image提前编译生成与本地机器相关的可执行文件。与在JVM执行java程序相比,Native Image占用内存更小和启动速度更快。

从spring boot3开始支持GraalVM Native Image,因此要使用此特性,需要把spring boot升级到3.0.0以上, 其中,JDK也要升级到17以上。

官方提供的示例见Developing Your First GraalVM Native Application。示例代码与普通spring boot一样,可以忽略,继续看下面内容。

1.1 maven插件配置

示例中与spring boot项目一样,不同之处在于打包配置,比如maven pom.xml文件中需要加上graalvm的native-maven-plugin插件,如下:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0</version><relativePath/>
</parent><!--省略--><dependencies>
<!--省略-->
</dependencies><build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--其它插件--></plugins>
</build>

pom说明:<parent>项指定为spring-boot-starter-parent,这样你就可以减少许多配置,就像上面一样。
spring-boot-starter-parent中为生成Native Image定义了名为native的profile,打包生成可执行文件使用如下maven命令

mvn clean package -Pnative

1.2 maven插件完整配置

如果pom的<parent>项不是spring-boot-starter-parent,你就需要像如下配置

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.3.0</version><configuration><archive><manifestEntries><Spring-Boot-Native-Processed>true</Spring-Boot-Native-Processed></manifestEntries></archive></configuration>
</plugin>
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>3.3.0</version><configuration><image><builder>paketobuildpacks/builder-jammy-tiny:latest</builder><env><BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE></env></image></configuration><executions><execution><id>process-aot</id><goals><goal>process-aot</goal></goals></execution></executions>
</plugin>
<plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.10.2</version><configuration><classesDirectory>${project.build.outputDirectory}</classesDirectory></configuration><executions><execution><id>add-reachability-metadata</id><goals><goal>add-reachability-metadata</goal></goals></execution></executions>
</plugin>

2. 开发注意事项

Spring Boot对自身提供的bean自动注入、AOP配置、factories等特性做了Native支持,在静态编译期间相关类都可达,
但我们的项目中还有些不受spring AOT支持的代码,比如业务代码中的反射、JSON和对象转换、以及三方jar包中动态代码等。
我们需要手动配置提供hint,graalvm才能把这些动态代码编译到可执行文件中去,否则执行时会抛出异常。

2.1 项目中动态代码支持

提供动态代码的hint配置,有三种方式:

  1. 第一种遵从graalvm规范提供相应的json配置,这个可以见往期分享Graalvm配置文件与Feature和Substitute机制介绍
  2. 第二种扩展Spring接口,即实现RuntimeHintsRegistrar接口,通过代码指定哪些类、资源需要hint。
  3. 第三种反射类可以使用@RegisterReflectionForBinding由spring自动绑定反射配置。

下面介绍后面两种方式

2.1.1 扩展Spring接口RuntimeHintsRegistrar

  1. 示例代码如下:
    public class MyAOTRuntimeHints implements RuntimeHintsRegistrar {@Overridepublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {// Register method for reflection//        Method method = ReflectionUtils.findMethod(MyClass.class, "sayHello", String.class);//        hints.reflection().registerMethod(method, ExecutableMode.INVOKE);// 反射注册hints.reflection().registerType(UserModel.class, typeHint -> {typeHint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,MemberCategory.INVOKE_DECLARED_METHODS,MemberCategory.DECLARED_FIELDS);});// 资源文件注册hints.resources().registerPattern("resource_hint.properties");// Serialization类注册hints.serialization().registerType(Email.class);// 代理注册// hints.proxies().registerJdkProxy(MyInterface.class);}
    }
    
  2. 注册Hint类。MyAOTRuntimeHints还需要使用@ImportRuntimeHints注解到任何@Configuration class,或者在META-INF/aot.factories文件注册
    1. 使用@ImportRuntimeHints
      @Configuration
      @ImportRuntimeHints(value = {MyAOTRuntimeHints.class})
      public class AOTConfiguration {}
      
    2. 注册META-INF/aot.factories
      org.springframework.aot.hint.RuntimeHintsRegistrar=com.example.springnative.aot.hit.MyAOTRuntimeHints
      

2.1.2 使用注解@RegisterReflectionForBinding

对于项目中使用反射的地方,可以直接通过注解来配置hint,把@RegisterReflectionForBinding注解到任何@Configuration class类上。
示例如下:

@Configuration
@RegisterReflectionForBinding(classes = {MyJSONBean.class})
public class AOTConfiguration {}

2.2 代码中隐式使用反射的地方

2.2.1 JSON

json工具推荐使用jackson,spring中也对其做了支持。
把对象转为json或把json转为对象,对象中所有类都要注册反射hint。
如UserModel在在reflect-config.json配置如下

{
"name": "com.example.springnative.model.UserModel",
"allPublicConstructors": true,
"allDeclaredFields": true,
"allPublicMethods": true
}

如果javabean实现了java.io.Serializable接口,可以在serialization-config.json中注册,示例如下。

{
"name": "com.example.springnative.model.UserModel"
}

2.3 Configuration Properties类嵌套

如果Properties类嵌套了其它类型,则必须要使用@NestedConfigurationProperty注解,否则spring AOT没法识别到这个嵌套类,就不能为其注册反射hint。如下示例。

@ConfigurationProperties(prefix = "my.properties")
public class MyProperties {@NestedConfigurationPropertyprivate final Nested nested = new Nested();// getters / setters...
}public class Nested {private int number;// getters / setters...}

2.4 Native Image执行与JVM执行区别

  1. 应用程序类路径在生成时是固定的,不能更改。
  2. 没有延迟类加载,可执行文件中提供的所有内容都将在启动时加载到内存中。
  3. 应用程序中定义的Bean不能在运行时更改,即bean创建相关的条件配置在编译后就不能再更改。
    如@Profile注解及类似配置不能更改,@ConditionalOnProperty中的条件值不能更改,即使更改也不会生效,因为bean已经创建了。

3. 原理简述

  1. Spring AOT Processor会启动应用main方法开始静态分析,并生成BeanDefinition对象,但不会创建bean
  2. 分析阶段不可达的代码将被忽略,不会编译到可执行文件中。
  3. 在编译前会生成java代码来创建BeanDefinition对象。源码存放到target/spring-aot/main/sources
  4. AOP原本在运行时动态生成的字节码,但在编译时就必须生成,动态字节码存放在target/spring-aot/main/classes
  5. Spring AOT Processor生成native需要的hint文件,存放到target/spring-aot/main/resources
  6. Spring boot把所有生成的文件都编译到jar包中,关于hint文件都放到jar包的META-INF/native-image目录下,graalvm静态编译时会获取该目录下的hint配置文件。

4. 官方文档阅读

Known GraalVM Native Image limitations

Testing GraalVM Native Images

Introducing GraalVM Native Images

5. 总结

  1. maven插件配置有两种方式,
    1. 一种是pom的parent指定为spring-boot-starter-parent后简单引入spring的spring-boot-maven-plugin和graalvm的native-maven-plugin插件
    2. 另一种是完整的配置spring的spring-boot-maven-plugin插件指定process-aot目标,配置graalvm的native-maven-plugin插件指定add-reachability-metadata目标
  2. 动态代码需要由开发者指定hint配置,有3种方式:
    1. 使用graalvm原生支持的方式,在META-INF/native-image目录下添加反射、代理、JNI等相关json配置。
    2. 实现RuntimeHintsRegistrar接口通过代码方式注册hint配置。
    3. 反射类可以使用@RegisterReflectionForBinding由spring自动绑定反射配置。
  3. 编译后影响bean创建相关的配置在运行期间不起作用,如@ConditionalOnProperty中的条件。

相关文章:

Spring Boot应用使用GraalVM本地编译相关配置

1. 介绍 Java应用程序可以通过Graalvm Native Image提前编译生成与本地机器相关的可执行文件。与在JVM执行java程序相比&#xff0c;Native Image占用内存更小和启动速度更快。 从spring boot3开始支持GraalVM Native Image&#xff0c;因此要使用此特性&#xff0c;需要把sp…...

代码的坏味道——长函数

前言&#xff1a;一个函数应该尽量做一件事情&#xff0c;如果非要做多个事情&#xff0c;要做函数提取&#xff0c;每次迭代应该考虑到是否有重复代码或者可以优化的代码。 长函数&#xff1a;长函数的产生&#xff1a; 逻辑是平铺直叙的需求迭代没有考虑优化&#xff0c;一次…...

【机器学习】基于密度的聚类算法:DBSCAN详解

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 基于密度的聚类算法&#xff1a;DBSCAN详解引言DBSCAN的基本概念点的分类聚类过…...

Qt 网络编程 网络信息获取操作

学习目标&#xff1a;网络信息获取操作 前置环境 运行环境:qt creator 4.12 学习内容 一、Qt 网络编程基础 Qt 直接提供了网络编程模块,包括基于 TCP/IP 的客户端和服务器相关类,如 QTcpSocket/QTcpServer 和 QUdpSocket,以及实现 HTTP、FTP 等协议的高级类,如 QNetworkRe…...

linux中的进程以及进程管理

程序和进程的区别和联系 程序&#xff08;Program&#xff09;&#xff1a; 程序是一组指令的集合&#xff0c;通常存储在磁盘或其他存储设备上&#xff0c;是一种静态的概念。程序本身并没有运行&#xff0c;它只是一个可执行的文件或脚本&#xff0c;包含了一系列的指令和数…...

pyecharts可视化案例大全(11~20)

pyecharts可视化案例大全(11~20) 十一、设置动画效果十二、直方图带视觉组件十三、设置渐变色(线性渐变)十四、设置渐变色(径向渐变)十五、设置分割线十六、设置分隔区域十七、面积图十八、堆叠面积图十九、自定义线样式二十、折线图平滑处理十一、设置动画效果 在图表加载前…...

Docker在人工智能领域的应用与实战

摘要 人工智能&#xff08;AI&#xff09;技术的快速发展带来了对高效开发和部署工具的需求。Docker作为一个创新的容器化平台&#xff0c;为AI领域提供了强大的支持。本文详细介绍了Docker在AI模型开发、训练、部署以及服务器集群管理等方面的应用&#xff0c;并探讨了其在数…...

python基础篇(8):异常处理

在Python编程中&#xff0c;异常是程序运行时发生的错误&#xff0c;它会中断程序的正常执行流程。异常处理机制使得程序能够捕获这些错误&#xff0c;并进行适当的处理&#xff0c;从而避免程序崩溃。 1 错误类型 代码的错误一般会有语法错误和异常错误两种&#xff0c;语法错…...

FortiClient 用IPsec VPN 远程拨号到FortiGate说明文档

说明&#xff1a;本文档针对IPsec VPN 中的Remote VPN 进行说明&#xff0c;即远程用户使用PC中的FortiClient软件&#xff0c;通过VPN拨号的方式连接到公司总部FortiGate设备&#xff0c;访问公司内部服务器。在配置之前需要统一VPN策略和参数&#xff0c;如模式… 说明&#…...

Git-Unity项目版本管理

目录 准备GitHub新建项目并添加ssh密钥Unity文件夹 本文记录如何用git对unity 项目进行版本管理&#xff0c;并可传至GitHub远端。 准备 名称版本windows11Unity2202.3.9.f1gitN.A.githubN.A. GitHub新建项目并添加ssh密钥 GitHub新建一个repositorywindows11 生成ssh-key&…...

每日一题~ leetcode 402 (贪心+单调栈)

click me! 这个贪心的推导在leetcode上已经很明确了。 click me! 删除k个数&#xff0c;可以先考虑删除一个数。这也是一种常见的思路。&#xff08;如果进行同样的操作多次&#xff0c;可以先只 考虑一次操作如何实现&#xff0c;或者他的影响。完成这一次操作后&#xff0c;…...

设计模式之模版方法

模版方法介绍 模版方法&#xff08;Template Method&#xff09;模式是一种行为型设计模式&#xff0c;它定义了一个操作&#xff08;模板方法&#xff09;的基本组合与控制流程&#xff0c;将一些步骤&#xff08;抽象方法&#xff09;推迟到子类中&#xff0c;使得子类可以在…...

docker部署redis/mongodb/

一、redis 创建/root/redis/conf/redis.conf 全部执行命令如下 docker run -it -d --name redis -p 6379:6379 --net mynet --ip 172.18.0.9 -m 400m -v /root/redis/conf:/usr/local/etc/redis -e TXAsia/Shangehai redis redis-server /usr/local/etc/redis/redis.conf 部署…...

LeetCode 581. 最短无序连续子数组

更多题解尽在 https://sugar.matrixlab.dev/algorithm 每日更新。 组队打卡&#xff0c;更多解法等你一起来参与哦&#xff01; LeetCode 581. 最短无序连续子数组&#xff0c;难度中等。 排序 解题思路&#xff1a;首先对数组排序&#xff0c;然后找出两侧顺序的数组&#x…...

数据库可视化管理工具dbeaver试用及问题处理。

本文记录了在内网离线安装数据库可视化管理工具dbeaver的过程和相关问题处理方法。 一、下载dbeaver https://dbeaver.io/download/ 笔者测试时Windows平台最新版本为&#xff1a;dbeaver-ce-24.1.1-x86_64-setup.exe 二、安装方法 一路“下一步”即可 三、问题处理 1、问…...

29、php实现和为S的两个数字(含源码)

题目&#xff1a;php 实现 和为S的两个数字 描述&#xff1a; 输入一个递增排序的数组和一个数字S&#xff0c;在数组中查找两个数&#xff0c; 是的他们的和正好是S&#xff0c;如果有多对数字的和等于S&#xff0c;输出两个数的乘积最小的。 输出描述&#xff1a; 对应每个测…...

Spring Boot中的全局异常处理

Spring Boot中的全局异常处理 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将探讨如何在Spring Boot应用中实现全局异常处理&#xff0c;这是保证应用…...

中英双语介绍美国苹果公司(Apple Inc.)

中文版 苹果公司简介 苹果公司&#xff08;Apple Inc.&#xff09;是一家美国跨国科技公司&#xff0c;总部位于加利福尼亚州库比蒂诺。作为全球最有影响力的科技公司之一&#xff0c;苹果以其创新的产品和设计引领了多个科技领域的变革。以下是对苹果公司发展历史、主要产品…...

C语言牢大坠机

目录 开头程序程序的流程图《牢大坠机》结尾 开头 大家好&#xff0c;我叫这是我58&#xff0c;今天&#xff0c;我们要来看关于牢大坠机的一些东西。 程序 #define _CRT_SECURE_NO_WARNINGS 1 #define HIGH 66 #include <stdio.h> #include <Windows.h> int ma…...

zdppy+vue3+antd 实现表格单元格编辑功能

初步实现 <template><a-button class"editable-add-btn" style"margin-bottom: 8px" click"handleAdd">Add</a-button><a-table bordered :data-source"dataSource" :columns"columns"><templa…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

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

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

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...