惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Simon Willison's Weblog
Simon Willison's Weblog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
Last Week in AI
Last Week in AI
月光博客
月光博客
有赞技术团队
有赞技术团队
P
Proofpoint News Feed
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
U
Unit 42
The Register - Security
The Register - Security
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hugging Face - Blog
Hugging Face - Blog
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
D
DataBreaches.Net
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
H
Hacker News: Front Page
Recent Announcements
Recent Announcements
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
小众软件
小众软件
P
Palo Alto Networks Blog
PCI Perspectives
PCI Perspectives
Security Latest
Security Latest
S
Secure Thoughts
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threat Research - Cisco Blogs
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
O
OpenAI News
S
Securelist
云风的 BLOG
云风的 BLOG
H
Help Net Security
T
Troy Hunt's Blog

Liu Zijian's Blog | 一个技术博客

使用Certbot自动续签HTTPS证书 使用Filebeat采集Nginx日志到ES Python的协程 Python中的异常 Python中的类和对象 Python的函数 Python的数据结构,推导式、迭代器和生成器 Spring AI集成多模态模型 LangChain4j多模态 LangChain Tools工具使用 Python中的模块和包 Python全局环境和虚拟环境(venv) LangChain Prompt提示词工程 LangChain4j Tools工具使用 基于Dify搭建AI智能体应用 LangChain4j RAG检索增强生成 Spring AI实现MCP Server Spring AI集成MCP Client LangChain4j Prompt提示词工程 Spring AI使用知识库增强对话功能 Spring AI实现一个智能客服 Spring AI实现一个简单的对话机器人 实现MinIO数据的每日备份 自己实现一个DNS服务 简单理解AI智能体 大模型和大模型应用 LangChain开篇 LangChain4j开篇 一个解析Excel2007的POI工具类 DataPermissionInterceptor源码解读 TenantLineInnerInterceptor源码解读 BaseMultiTableInnerInterceptor源码解读 Spring AI开篇 SQL解析工具JSQLParser 芋道源码解读之多租户 芋道源码解读之数据权限 芋道源码解读开篇 Java实现将数据导出为Word文档 OA系统的天数该怎样计算 安装MySQL8 安装MySQL5.7 RockyLinux9环境下编译MySQL8 MySQL字符集及底层原理 Java实现LDAP登录 Docker Compose IPv4和IPv6 使用虚拟机安装一个K8s集群 使用GraalVM原生编译打包SpringBoot工程 Nginx防止目录穿越 Java线程的状态 Nginx防盗链设置 使用python将excel表格转换为SQL INSERT Redis的公共操作命令 Redis数据结构之Bitfleid Redis数据结构之Bitmap Redis数据结构之GEO Redis数据结构之Hash Redis数据结构之HyperLogLog Redis数据结构之List Redis数据结构之Set Redis数据结构之Stream Redis数据结构之String Redis数据结构之ZSet 使用python压缩图片 利用Python实现Hexo站点的持续集成 Nginx设置HTTPS监听 firewalld防火墙工具的使用 Linux信号(signal)机制 MySQL5.7x 主从复制 用IP自签发一个HTTPS证书 基于Hexo实现一个静态的个人博客 RockyLinux9环境下编译MySQL5.7 Docker离线安装 MySQL数据定义语言 Docker与联合文件系统 Docker的网络 Docker的镜像操作 MySQL存储过程 MyBatis-Plus开篇 MySQL变量 MySQL视图 MySQL事务 MySQL插入修改和删除 MySQL查询 MySQL系统命令 Docker的容器操作 Docker的安装和配置 Docker容器数据卷 浅谈OAuth2.0授权原理 JVM开篇 浅谈Linux(Unix)的I/O模型 一个通用的CloseableHttpClient工厂类 JUC可重入锁ReentrantLock JUC读写锁ReadWriteLock Java的单例 Java泛型 Java8的新特性 最近最少使用算法(LRU) MySQL函数 SpringBoot配置和启动
使用GraalVM原生编译打包SpringBoot工程
Liu Zijian · 2024-11-10 · via Liu Zijian's Blog | 一个技术博客

1.GraalVM

GraalVM (https://www.graalvm.org/) 是一个高性能的JDK,旨在加速用Java和其他JVM语言编写的应用程序的执行,同时还提供JavaScript,python和许多其他流行语言的运行时。

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

  1. 在hotspot jvm上使用graal即时编译器(JIT)
  2. 作为预先编译的本机可执行文件运行

GraalVM的多语言能力使得在单个应用程序中混合多种编程语言成为可能,同时消除了外部语言的调用成本。

2.Windows平台安装和配置GraalVM

Windows平台环境安装和配置比较复杂

2.1 安装Visual Studio

Visual Studio(特别是其中的 Visual C++ 工具)在 Windows 系统上提供了 C/C++ 编译器和相关工具链,它们是用来编译和链接本地代码的。当使用 GraalVM 在 Windows 上构建本地可执行文件时,需要依赖 Visual Studio 提供的这些编译工具来完成编译和链接的过程。

安装界面,勾选使用C++的桌面开发

等待安装完成后,测试x64 Native Tools Command Prompt for VS 2022

以管理员身份测试打开x64 Native Tools Command Prompt for VS 2022

2.2 Windows安装GraalVM并配置

打开社区版GraalVM下载的GitHub页面
https://github.com/graalvm/graalvm-ce-builds/releases

以22.3.3版Java17为例,找到22.3.3版本,分别下载Windows平台的GraalVM graalvm-ce-java17-windows-amd64-22.3.3.zip和调用底层工具的原生镜像支持工具native-image-installable-svm-java17-windows-amd64-22.3.3.jar

下载地址:

  • graalvm-ce-java17-windows-amd64-22.3.3.zip

https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.3/graalvm-ce-java17-windows-amd64-22.3.3.zip

  • native-image-installable-svm-java17-windows-amd64-22.3.3.jar

https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.3/native-image-installable-svm-java17-windows-amd64-22.3.3.jar

设置环境变量

将GraalVM压缩包解压到F:\graalvm-ce-java17-22.3.3,然后设置环境变量JAVA_HOMEF:\graalvm-ce-java17-22.3.3,设置环境变量PATH新增%JAVA_HOME%/bin

检查环境变量生效

java -version

安装native-image

在jar包目录打开cmd窗口,输入命令,完成安装

gu install --file ./native-image-installable-svm-java17-windows-amd64-22.3.3.jar

输入命令,测试是否安装成功

native-image

至此,Windows平台GraalVM和支持将应用打包成本地镜像的工具安装配置完成。

2.3 新建简单项目测试编译打包

打开IDEA,新建项目springboot3,JDK选择安装的graalvm-ce-java17,然后先编写一段非常简单的Java代码,然后将其编译为原生.exe可执行文件

public class Main {
    public static void main(String[] args) {
        System.out.printf("hello graalvm!");
    }
}

用Maven将项目打包为jar包

打开x64 Native Tools Command Prompt for VS 2022工具,使用底层能力运行native-image工具,将class编译为.exe。

以管理员身份打开x64 Native Tools Command Prompt for VS 2022,并CD切换到jar包所在target目录,然后执行命令

-cp 编译
-o 目标.exe文件名称

native-image -cp ./springboot3-1.0-SNAPSHOT.jar org.example.Main -o springboot3

编译完成,生成Windows平台的.exe可执行文件

打开CMD,执行exe文件,输出代码运行结果,和Java虚拟机解释执行结果相同

2.4 新建SpringBoot3项目测试编译打包

首先要在Windows下配置三个环境变量,每个人环境和位置不同,需要自己按照自己的实际情况新增或修改。

1.path

path环境变量新增以下路径

F:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\bin\Hostx64\x64

2.lib

新建lib环境变量,并将以下路径配置进去,之间用英文分号;间隔,以下位置目录均为VS创建

F:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\lib\x64
F:\Windows Kits\10\Lib\10.0.22621.0\ucrt\x64
F:\Windows Kits\10\Lib\10.0.22621.0\um\x64

3.INCLUDE(大写)

新建INCLUDE环境变量,并将以下路径配置进去,之间用英文分号;间隔,以下位置目录均为VS创建

F:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\include
F:\Windows Kits\10\Include\10.0.22621.0\shared
F:\Windows Kits\10\Include\10.0.22621.0\ucrt
F:\Windows Kits\10\Include\10.0.22621.0\um
F:\Windows Kits\10\Include\10.0.22621.0\winrt

! ! !环境变量配置好后,一定要重新打开CMD窗口编译打包,使用Intellij IDEA的,一定也要重启IDEA。

接下来,编写一个简单的SpringBoot应用,并编译打包为原生.exe文件

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">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.6</version>
    </parent>

    <groupId>org.example</groupId>
    <artifactId>springboot3</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </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>


</project>

org.example.controller.TestController

package org.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("test")
public class TestController {

    @GetMapping("hello")
    public String hello(String s) {
        return "hello " + s;
    }
}

org.example.Main

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class);
    }
}

application.yml

server:
  port: 8081

接下来先用普通的编译命令将代码编译为.class文件。

然后,执行spring-bootprocess-aot插件,进行编译前的前置处理。

前置处理完成后,target目录下生成了一些AOT编译相关的文件,用于指定主类的位置等

最后,运行native插件的build启动native-image,调用VS工具链将工程编译为二进制.exe文件

开始编译后等待编译完成


我的IDEA输出:

[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< org.example:springboot3 >-----------------------
[INFO] Building springboot3 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- native-maven-plugin:0.9.21:build (default-cli) @ springboot3 ---
[WARNING] 'native:build' goal is deprecated. Use 'native:compile-no-fork' instead.
[INFO] Found GraalVM installation from JAVA_HOME variable.
[INFO] Executing: F:\graalvm-ce-java17-22.3.3\bin\native-image.cmd @target\tmp\native-image-3043011469918092793.args
========================================================================================================================
GraalVM Native Image: Generating 'springboot3' (executable)...
========================================================================================================================
[1/7] Initializing...                                                                                   (21.0s @ 0.17GB)
 Version info: 'GraalVM 22.3.3 Java 17 CE'
 Java version info: '17.0.8+7-jvmci-22.3-b22'
 C compiler: cl.exe (microsoft, x64, 19.41.34123)
 Garbage collector: Serial GC
 1 user-specific feature(s)
 - org.springframework.aot.nativex.feature.PreComputeFieldFeature
Field org.apache.commons.logging.LogAdapter#log4jSpiPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#log4jSlf4jProviderPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#slf4jSpiPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#slf4jApiPresent set to true at build time
Field org.springframework.core.NativeDetector#imageCode set to true at build time
Field org.springframework.core.KotlinDetector#kotlinPresent set to false at build time
Field org.springframework.core.KotlinDetector#kotlinReflectPresent set to false at build time
Field org.springframework.format.support.DefaultFormattingConversionService#jsr354Present set to false at build time
Field org.springframework.cglib.core.AbstractClassGenerator#imageCode set to true at build time
Field org.springframework.boot.logging.log4j2.Log4J2LoggingSystem$Factory#PRESENT set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#romePresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jaxb2Present set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2Present set to true at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2XmlPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2SmilePresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2CborPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#gsonPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jsonbPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#kotlinSerializationCborPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#kotlinSerializationJsonPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#kotlinSerializationProtobufPresent set to false at build time
Field org.springframework.boot.logging.java.JavaLoggingSystem$Factory#PRESENT set to true at build time
Field org.springframework.boot.logging.logback.LogbackLoggingSystem$Factory#PRESENT set to true at build time
Field org.springframework.http.converter.json.Jackson2ObjectMapperBuilder#jackson2XmlPresent set to false at build time
Field org.springframework.web.servlet.view.InternalResourceViewResolver#jstlPresent set to false at build time
Field org.springframework.web.context.support.StandardServletEnvironment#jndiPresent set to true at build time
Field org.springframework.boot.logging.logback.LogbackLoggingSystemProperties#JBOSS_LOGGING_PRESENT set to false at build time
Field org.springframework.web.context.support.WebApplicationContextUtils#jsfPresent set to false at build time
Field org.springframework.web.context.request.RequestContextHolder#jsfPresent set to false at build time
Field org.springframework.context.event.ApplicationListenerMethodAdapter#reactiveStreamsPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jaxb2Present set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jackson2Present set to true at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jackson2XmlPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jackson2SmilePresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#gsonPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jsonbPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#kotlinSerializationCborPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#kotlinSerializationJsonPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#kotlinSerializationProtobufPresent set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#reactorPresent set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#rxjava3Present set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#kotlinCoroutinesPresent set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#mutinyPresent set to false at build time
Field org.springframework.web.client.RestTemplate#romePresent set to false at build time
Field org.springframework.web.client.RestTemplate#jaxb2Present set to false at build time
Field org.springframework.web.client.RestTemplate#jackson2Present set to true at build time
Field org.springframework.web.client.RestTemplate#jackson2XmlPresent set to false at build time
Field org.springframework.web.client.RestTemplate#jackson2SmilePresent set to false at build time
Field org.springframework.web.client.RestTemplate#jackson2CborPresent set to false at build time
Field org.springframework.web.client.RestTemplate#gsonPresent set to false at build time
Field org.springframework.web.client.RestTemplate#jsonbPresent set to false at build time
Field org.springframework.web.client.RestTemplate#kotlinSerializationCborPresent set to false at build time
Field org.springframework.web.client.RestTemplate#kotlinSerializationJsonPresent set to false at build time
Field org.springframework.web.client.RestTemplate#kotlinSerializationProtobufPresent set to false at build time
Field org.springframework.boot.autoconfigure.web.format.WebConversionService#JSR_354_PRESENT set to false at build time
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
Field org.springframework.web.servlet.mvc.method.annotation.ReactiveTypeHandler#isContextPropagationPresent set to false at build time
Field org.springframework.web.servlet.support.RequestContext#jstlPresent set to false at build time
[2/7] Performing analysis...  [**********]                                                              (98.5s @ 1.27GB)
  15,315 (92.75%) of 16,513 classes reachable
  24,931 (67.59%) of 36,886 fields reachable
  73,546 (62.21%) of 118,224 methods reachable
     802 classes,   244 fields, and 4,549 methods registered for reflection
      83 classes,    78 fields, and    68 methods registered for JNI access
       5 native libraries: crypt32, ncrypt, psapi, version, winhttp
[3/7] Building universe...                                                                               (9.2s @ 1.48GB)
[4/7] Parsing methods...      [**]                                                                       (3.0s @ 1.71GB)
[5/7] Inlining methods...     [***]                                                                      (2.1s @ 1.75GB)
[6/7] Compiling methods...    [*********]                                                               (92.6s @ 1.80GB)
[7/7] Creating image...                                                                                (162.3s @ 1.29GB)
  34.44MB (52.32%) for code area:    48,187 compilation units
  30.94MB (47.01%) for image heap:  354,772 objects and 118 resources
 445.88KB ( 0.66%) for other data
  65.81MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 packages in code area:                               Top 10 object types in image heap:
   1.64MB sun.security.ssl                                     7.33MB byte[] for code metadata
   1.05MB java.util                                            3.64MB java.lang.Class
 835.67KB java.lang.invoke                                     3.41MB java.lang.String
 725.04KB com.sun.crypto.provider                              2.87MB byte[] for general heap data
 560.78KB org.apache.catalina.core                             2.83MB byte[] for java.lang.String
 527.20KB org.apache.tomcat.util.net                           1.29MB com.oracle.svm.core.hub.DynamicHubCompanion
 495.45KB org.apache.coyote.http2                            880.07KB byte[] for reflection metadata
 477.20KB java.lang                                          775.15KB byte[] for embedded resources
 470.10KB c.s.org.apache.xerces.internal.impl.xs.traversers  664.68KB java.lang.String[]
 467.89KB java.util.concurrent                               621.94KB java.util.HashMap$Node
  26.94MB for 621 more packages                                5.69MB for 3067 more object types
------------------------------------------------------------------------------------------------------------------------
                      134.1s (26.7% of total time) in 116 GCs | Peak RSS: 2.60GB | CPU load: 3.09
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
 C:\Users\LiuZijian\IdeaProjects\springboot3\target\springboot3.build_artifacts.txt (txt)
 C:\Users\LiuZijian\IdeaProjects\springboot3\target\springboot3.exe (executable)
========================================================================================================================
Finished generating 'springboot3' in 8m 20s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  08:30 min
[INFO] Finished at: 2024-11-14T23:22:01+08:00
[INFO] ------------------------------------------------------------------------

Process finished with exit code 0

编译完成,得到.exe文件

运行编译成的.exe文件并测试

.exe文件很快启动,并可以正常处理http请求,虽然命令窗口打印存在问题,但是接口是能调通的,文章写到这已经很晚了,故这个问题先留着后续有空解决…

3.linux平台安装和配置GraalVM

Linux平台安装和配置GraalVM,我使用Ubuntu22进行测试

3.1 安装Linux编译工具链

编译native-image,需要安装Linux下的编译环境

sudo apt-get install build-essential libz-dev zlib1g-dev

! tips: 如果是redhat系列linux,可能需要这样安装

sudo yum install -y gcc glibc glibc-devel zlib-devel

3.2 Linux下载安装GraalVM

接下来,和Windows系统一样,下载GraalVMnative-image的Linux x64版本,我在这里还是选择和Windows一样的22.3.3版本。

下载地址仍然是 https://github.com/graalvm/graalvm-ce-builds/releases

  • graalvm-ce-java17-linux-amd64-22.3.3.tar.gz

https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.3/graalvm-ce-java17-linux-amd64-22.3.3.tar.gz

  • native-image-installable-svm-java17-linux-amd64-22.3.3.jar

https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.3/native-image-installable-svm-java17-linux-amd64-22.3.3.jar

将下载好的两个文件移动到/opt目录下,解压graalvm-ce-java17-linux-amd64-22.3.3.tar.gz到路径/opt并设置环境变量

解压到/opt

tar -zxvf ./graalvm-ce-java17-linux-amd64-22.3.3.tar.gz

打开/etc/profile设置环境变量

vim /etc/profile

将下面两句放在文件最末尾

export JAVA_HOME=/opt/graalvm-ce-java17-22.3.3
export PATH=$PATH:$JAVA_HOME/bin

刷新,使环境变量生效

source /etc/profile

返回/opt目录,安装native-image.jar原生镜像打包工具包,命令和Windows之前安装的命令完全相同

cd /opt

gu install --file ./native-image-installable-svm-java17-linux-amd64-22.3.3.jar

验证JAVA_HOME变量是否生效,native-image.jar是否正确安装

java -version

native-image

3.3 编译打包SpringBoot项目

首先需要安装Linux环境的maven,并设置好环境变量,然后将工程源码拷贝到/opt目录下,然后依次执行maven命令。

先用普通的编译命令将代码编译为.class文件

mvn run compile

然后,执行spring-bootprocess-aot插件,进行编译前的前置处理

mvn spring-boot:process-aot

开始编译,运行native插件的build启动native-image,调用Linux底层工具链将工程编译为Linux平台的二进制文件

mvn  native:build

终端输出

root@lzj-virtual-machine:/opt/springboot3# mvn  native:build
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< org.example:springboot3 >-----------------------
[INFO] Building springboot3 1.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- native:0.9.21:build (default-cli) @ springboot3 ---
[WARNING] 'native:build' goal is deprecated. Use 'native:compile-no-fork' instead.
[INFO] Found GraalVM installation from JAVA_HOME variable.
[INFO] Executing: /opt/graalvm-ce-java17-22.3.3/bin/native-image -cp /opt/springboot3/target/classes:/root/.m2/repository/org/springframework/boot/spring-boot-starter/3.0.6/spring-boot-starter-3.0.6.jar:/root/.m2/repository/ch/qos/logback/logback-classic/1.4.7/logback-classic-1.4.7.jar:/root/.m2/repository/org/slf4j/slf4j-api/2.0.7/slf4j-api-2.0.7.jar:/root/.m2/repository/io/micrometer/micrometer-observation/1.10.6/micrometer-observation-1.10.6.jar:/root/.m2/repository/org/springframework/spring-expression/6.0.8/spring-expression-6.0.8.jar:/root/.m2/repository/ch/qos/logback/logback-core/1.4.7/logback-core-1.4.7.jar:/root/.m2/repository/org/springframework/spring-webmvc/6.0.8/spring-webmvc-6.0.8.jar:/root/.m2/repository/org/springframework/boot/spring-boot/3.0.6/spring-boot-3.0.6.jar:/root/.m2/repository/org/springframework/boot/spring-boot-starter-logging/3.0.6/spring-boot-starter-logging-3.0.6.jar:/root/.m2/repository/org/springframework/boot/spring-boot-starter-json/3.0.6/spring-boot-starter-json-3.0.6.jar:/root/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.14.2/jackson-datatype-jsr310-2.14.2.jar:/root/.m2/repository/org/springframework/spring-aop/6.0.8/spring-aop-6.0.8.jar:/root/.m2/repository/jakarta/annotation/jakarta.annotation-api/2.1.1/jakarta.annotation-api-2.1.1.jar:/root/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/10.1.8/tomcat-embed-websocket-10.1.8.jar:/root/.m2/repository/org/springframework/spring-context/6.0.8/spring-context-6.0.8.jar:/root/.m2/repository/org/slf4j/jul-to-slf4j/2.0.7/jul-to-slf4j-2.0.7.jar:/root/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.14.2/jackson-databind-2.14.2.jar:/root/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.14.2/jackson-datatype-jdk8-2.14.2.jar:/root/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/3.0.6/spring-boot-autoconfigure-3.0.6.jar:/root/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/10.1.8/tomcat-embed-el-10.1.8.jar:/root/.m2/repository/io/micrometer/micrometer-commons/1.10.6/micrometer-commons-1.10.6.jar:/root/.m2/repository/org/apache/logging/log4j/log4j-api/2.19.0/log4j-api-2.19.0.jar:/root/.m2/repository/org/springframework/spring-web/6.0.8/spring-web-6.0.8.jar:/root/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.14.2/jackson-module-parameter-names-2.14.2.jar:/root/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.19.0/log4j-to-slf4j-2.19.0.jar:/root/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/10.1.8/tomcat-embed-core-10.1.8.jar:/root/.m2/repository/org/springframework/spring-core/6.0.8/spring-core-6.0.8.jar:/root/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.14.2/jackson-annotations-2.14.2.jar:/root/.m2/repository/org/yaml/snakeyaml/1.33/snakeyaml-1.33.jar:/root/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.14.2/jackson-core-2.14.2.jar:/root/.m2/repository/org/springframework/boot/spring-boot-starter-web/3.0.6/spring-boot-starter-web-3.0.6.jar:/root/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/3.0.6/spring-boot-starter-tomcat-3.0.6.jar:/root/.m2/repository/org/springframework/spring-jcl/6.0.8/spring-jcl-6.0.8.jar:/root/.m2/repository/org/springframework/spring-beans/6.0.8/spring-beans-6.0.8.jar --no-fallback -H:Path=/opt/springboot3/target -H:Name=springboot3
========================================================================================================================
GraalVM Native Image: Generating 'springboot3' (executable)...
========================================================================================================================
[1/7] Initializing...                                                                                   (38.9s @ 0.18GB)
 Version info: 'GraalVM 22.3.3 Java 17 CE'
 Java version info: '17.0.8+7-jvmci-22.3-b22'
 C compiler: gcc (linux, x86_64, 11.4.0)
 Garbage collector: Serial GC
 1 user-specific feature(s)
 - org.springframework.aot.nativex.feature.PreComputeFieldFeature
Field org.springframework.core.NativeDetector#imageCode set to true at build time
Field org.apache.commons.logging.LogAdapter#log4jSpiPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#log4jSlf4jProviderPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#slf4jSpiPresent set to true at build time
Field org.apache.commons.logging.LogAdapter#slf4jApiPresent set to true at build time
Field org.springframework.core.KotlinDetector#kotlinPresent set to false at build time
Field org.springframework.core.KotlinDetector#kotlinReflectPresent set to false at build time
Field org.springframework.cglib.core.AbstractClassGenerator#imageCode set to true at build time
Field org.springframework.format.support.DefaultFormattingConversionService#jsr354Present set to false at build time
Field org.springframework.boot.logging.logback.LogbackLoggingSystem$Factory#PRESENT set to true at build time
Field org.springframework.web.servlet.view.InternalResourceViewResolver#jstlPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#romePresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jaxb2Present set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2Present set to true at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2XmlPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2SmilePresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jackson2CborPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#gsonPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#jsonbPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#kotlinSerializationCborPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#kotlinSerializationJsonPresent set to false at build time
Field org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#kotlinSerializationProtobufPresent set to false at build time
Field org.springframework.boot.logging.log4j2.Log4J2LoggingSystem$Factory#PRESENT set to false at build time
Field org.springframework.boot.logging.java.JavaLoggingSystem$Factory#PRESENT set to true at build time
Field org.springframework.http.converter.json.Jackson2ObjectMapperBuilder#jackson2XmlPresent set to false at build time
Field org.springframework.web.context.support.StandardServletEnvironment#jndiPresent set to true at build time
Field org.springframework.web.context.support.WebApplicationContextUtils#jsfPresent set to false at build time
Field org.springframework.web.context.request.RequestContextHolder#jsfPresent set to false at build time
Field org.springframework.boot.logging.logback.LogbackLoggingSystemProperties#JBOSS_LOGGING_PRESENT set to false at build time
Field org.springframework.context.event.ApplicationListenerMethodAdapter#reactiveStreamsPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jaxb2Present set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jackson2Present set to true at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jackson2XmlPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jackson2SmilePresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#gsonPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#jsonbPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#kotlinSerializationCborPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#kotlinSerializationJsonPresent set to false at build time
Field org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter#kotlinSerializationProtobufPresent set to false at build time
Field org.springframework.web.client.RestTemplate#romePresent set to false at build time
Field org.springframework.web.client.RestTemplate#jaxb2Present set to false at build time
Field org.springframework.web.client.RestTemplate#jackson2Present set to true at build time
Field org.springframework.web.client.RestTemplate#jackson2XmlPresent set to false at build time
Field org.springframework.web.client.RestTemplate#jackson2SmilePresent set to false at build time
Field org.springframework.web.client.RestTemplate#jackson2CborPresent set to false at build time
Field org.springframework.web.client.RestTemplate#gsonPresent set to false at build time
Field org.springframework.web.client.RestTemplate#jsonbPresent set to false at build time
Field org.springframework.web.client.RestTemplate#kotlinSerializationCborPresent set to false at build time
Field org.springframework.web.client.RestTemplate#kotlinSerializationJsonPresent set to false at build time
Field org.springframework.web.client.RestTemplate#kotlinSerializationProtobufPresent set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#reactorPresent set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#rxjava3Present set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#kotlinCoroutinesPresent set to false at build time
Field org.springframework.core.ReactiveAdapterRegistry#mutinyPresent set to false at build time
Field org.springframework.boot.autoconfigure.web.format.WebConversionService#JSR_354_PRESENT set to false at build time
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
Field org.springframework.web.servlet.mvc.method.annotation.ReactiveTypeHandler#isContextPropagationPresent set to false at build time
Field org.springframework.web.servlet.support.RequestContext#jstlPresent set to false at build time
[2/7] Performing analysis...  [*********]                                                              (450.4s @ 2.25GB)
  15,331 (92.43%) of 16,586 classes reachable
  24,926 (67.58%) of 36,883 fields reachable
  73,471 (62.05%) of 118,406 methods reachable
     784 classes,   246 fields, and 4,536 methods registered for reflection
      64 classes,    70 fields, and    55 methods registered for JNI access
       4 native libraries: dl, pthread, rt, z
[3/7] Building universe...                                                                              (71.4s @ 1.81GB)
[4/7] Parsing methods...      [*******]                                                                 (48.4s @ 1.67GB)
[5/7] Inlining methods...     [***]                                                                     (18.7s @ 2.49GB)
[6/7] Compiling methods...    [**********]                                                             (112.1s @ 2.00GB)
[7/7] Creating image...                                                                                 (53.6s @ 2.85GB)
  33.97MB (51.08%) for code area:    48,119 compilation units
  29.90MB (44.97%) for image heap:  353,714 objects and 118 resources
   2.63MB ( 3.96%) for other data
  66.50MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 packages in code area:                               Top 10 object types in image heap:
   1.63MB sun.security.ssl                                     7.29MB byte[] for code metadata
   1.04MB java.util                                            3.64MB java.lang.Class
 829.18KB java.lang.invoke                                     3.41MB java.lang.String
 717.16KB com.sun.crypto.provider                              2.86MB byte[] for general heap data
 558.99KB org.apache.catalina.core                             2.82MB byte[] for java.lang.String
 519.74KB org.apache.tomcat.util.net                           1.29MB com.oracle.svm.core.hub.DynamicHubCompanion
 491.53KB org.apache.coyote.http2                            878.75KB byte[] for reflection metadata
 476.53KB java.lang                                          775.14KB byte[] for embedded resources
 467.23KB c.s.org.apache.xerces.internal.impl.xs.traversers  664.31KB java.lang.String[]
 461.61KB sun.security.x509                                  619.31KB java.util.HashMap$Node
  26.53MB for 628 more packages                                5.45MB for 3069 more object types
------------------------------------------------------------------------------------------------------------------------
                       189.1s (21.7% of total time) in 60 GCs | Peak RSS: 4.14GB | CPU load: 8.45
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
 /opt/springboot3/target/springboot3 (executable)
 /opt/springboot3/target/springboot3.build_artifacts.txt (txt)
========================================================================================================================
Finished generating 'springboot3' in 14m 28s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  14:40 min
[INFO] Finished at: 2024-11-16T00:59:34+08:00
[INFO] ------------------------------------------------------------------------

编译打包完成

编译完成,得到Linux上的可执行文件

运行可执行文件,并打开浏览器访问测试,功能正常

至此,Linux平台上原生镜像编译就完成了。

4.注意事项

  1. 不是所有Java代码都支持原生编译打包,例如代码中含有反射创建对象,反射调用方法等操作会导致AOT损失动态能力,如果编译需要额外处理,需要提前告知GraalVM未来会反射调用哪些方法或构造器,例如springboot就提供了一些注解,保证AOT编译时功能正常,但不是所有框架都像Spring那样适配了AOT

  2. 配置文件不能放进可执行文件,也需要额外处理,可以在程序代码改为相对路径读取配置文件。