当前位置:   article > 正文

Spring Boot 3.0 GA来啦,GraalVM Native Image Support初体验_graalvm native support

graalvm native support

Spring Boot 3.0 GA来啦,GraalVM Native Image Support初体验

前言

2022-11-25,SpringBoot 3.0.0 GA版本发布,带了Web Javaer万众期待的Cloud Native特性,这也意味着占据Java Web圈半壁江山的Spring框架正式进入真正的云原生时代。笔者作为一名多年的Java Web开发者,异常激动和兴奋,因为尽管java生态圈在全球开发领域占据非常大的份额,国内各类IT企业对Java已产生了很大的依赖性,简单来说Java为我们创造了很多价值,常年沉浸于Java开发工作,也发现了Java相比其他语言的缺陷与不足,尤其是进入容器化、云原生时代,其缺点尤为明显,主要表现在启动慢、占用内用大、笨重。Spring官方也一直在改进这些问题,但在3.0之前,一直没有好的解决方案,今天我们就来在Windows平台上尝鲜体验一下Spring Boot 3.0中的native特性。
在这里插入图片描述

Native Image

Spring Boot通过GraalVM(据说Oracle会将社区版捐献到OpenJDK中)来支持native images,取代了实验性的Spring Native项目。

GraalVM 本机映像是独立的可执行文件,运行不依赖JVM,可以通过提前处理已编译的 Java 应用程序来生成。Native Image通常具有较小的内存占用,并且启动速度比 JVM 对应项更快。在Windows上可编译为本地执行运行的exe程序。

与为 JVM 编写的传统应用程序不同,GraalVM 本机映像应用程序需要提前处理才能创建可执行文件。

这里要注意,Java应用程序要支持编译为Native Image,必须有一些前提条件,主要包括

  • GraalVM 不能支持代码的动态元素,必须编译前告知反射、资源、序列化和动态代理
  • 创建Native Image时将进行程序及依赖的所有代码分析,针对无法访问的代码将被删除,并且不会成为可执行文件的一部分
  • 应用程序的classpath在生成时是固定的,不能更改
  • 没有惰性类加载,可执行文件中附带的所有内容都将在启动时加载到内存中

总之,要编译成Native Image,必须消除程序中的动态元素

SpringBoot 3.0中上述这些静态化的额外操作已基本上通过Spring Aot在编译时动态处理,开发者无需额外的配置。

具体的处理细节大家可参考SpringBoot的官方文档

GraalVM安装

请前往GraalVM官网https://www.graalvm.org/downloads/ 下载 GraalVM Community 22.3,注意当前支持的Springboot的GraalVM版本必须是22.3

笔者这里下载的Java版本为17,如下图
在这里插入图片描述
安装GraalVM的方法与安装JAVA方法大致相同,GraalVM中包括了JDK,同时还需要安装native-image工具

注意该工具在编译时会自动检测是否存在,不存在时会自动下载,第一次下载会很慢。这里可以手动预先下载,并解压到GraalVM同目录下。

这里下载的文件为native-image-installable-svm-java17-windows-amd64-22.3.0.jar如下图所示

在这里插入图片描述

这是笔者安装完后的文件夹结构

在这里插入图片描述

配置环境变量PATH,JAVA_HOME

  setx /M PATH "C:\Progra~1\Java\<graalvm>\bin;%PATH%"
  setx /M JAVA_HOME "C:\Progra~1\Java\<graalvm>"
  • 1
  • 2

测试安装是否OK,如下图
在这里插入图片描述

Visual Studio安装

编译native image必须依赖VC++的编译环境,这里必须使用微软官方的vc++编译工具Visual Studio,笔者这里使用的最新版本2022,下面为官方描述

To use Native Image on Windows, install Visual Studio and Microsoft Visual C++ (MSVC).
There are two installation options:
    * Install the Visual Studio Build Tools with the Windows 10 SDK
    * Install Visual Studio with the Windows 10 SDK

You can use Visual Studio 2017 version 15.9 or later.

The `native-image` builder will only work when it is run from the **x64 Native Tools Command Prompt**.
The command for initiating an x64 Native Tools command prompt varies according to whether you only have the Visual Studio Build Tools installed or if you have the full Visual Studio 2019 installed.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

从上可知,Visual Studio 2017 version 15.9 or later均可。

打开Visual Studio Installer,勾选如下图中三个组件

在这里插入图片描述

安装完成后,需要配置VC++的编译环境变量PATH,INCLUDE,LIB

看相关文章也可不配置,但是执行编译时必须在X64 Native Tools Command Prompt for VS 2022控制台中执行,但笔者安装的环境下编译失败,提示找到 stdio.h 等错误,如果网友也遇到同样,欢迎提供更好的解决方案

LIB=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.20348.0\um\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.20348.0\ucrt\x64;D:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.16.27023\lib\x64

INCLUDE=C:\Program Files (x86)\Windows Kits\10\Include\10.0.20348.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.20348.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.20348.0\shared;D:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.16.27023\include

PATH=D:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64
  • 1
  • 2
  • 3
  • 4
  • 5

SpringBoot示例编写

可使用https://start.spring.io/来生成项目模板,完整的项目pom.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.0</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring_native_test</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <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>
</project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

编写一个简单的spring mvc应用

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created on ${DATE}.
 *
 * @author ${USER}
 */
@RestController
@SpringBootApplication
public class MyApplication {

    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

配置项目,注意这里必须选择GraalVM作为项目的SDK
在这里插入图片描述
调试运行,正常启动
在这里插入图片描述

native编译

在项目根目录下执行

mvn -Pnative native:compile

下图为最终执行成功的输出

在这里插入图片描述
在项目target目录下可以找到spring_native_test.exe文件

运行对比

native image运行控制台输出如下图
在这里插入图片描述
jvm运行控制台输出如下图
在这里插入图片描述

jar(JVM)本地exe(native image)
文件大小18M69M
启动耗时1.209s0.098s
内存占用106M46m

根据上述对比结果,尽管是一个最简单的springboot程序,但在启动耗时上native具有明显的优势,达到毫秒级,占用内存少了一半多。

由于是一项新技术,其推广和普及肯定需要一段时间,但在一些新的小型应用中,完全可以试试手,毕竟尽量native用不了,还有jvm可以兜底,我们并需要为此做额外的工作。

最后,希望java web能通过native的特性,真正的适配云原生。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/68645
推荐阅读
相关标签
  

闽ICP备14008679号