使用GraalVM将SpringBoot工程编译成平台原生的可执行文件
原文链接:https://blog.liuzijian.com/post/209e68d0-a418-1737-503a-d47e6d2d9350.html
1.GraalVM
GraalVM (https://www.graalvm.org/) 是一个高性能的JDK,旨在加速用Java和其他JVM语言编写的应用程序的执行,同时还提供JavaScript,python和许多其他流行语言的运行时。
GraalVM提供了两种运行Java应用程序的方式:
- 在hotspot jvm上使用graal即时编译器(JIT)
- 作为预先编译的本机可执行文件运行
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
- native-image-installable-svm-java17-windows-amd64-22.3.3.jar
设置环境变量
将GraalVM压缩包解压到F:\graalvm-ce-java17-22.3.3,然后设置环境变量JAVA_HOME
为F:\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-boot
的process-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系统一样,下载GraalVM
和native-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
- 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-boot
的process-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.注意事项
-
不是所有Java代码都支持原生编译打包,例如反射创建对象,反射调用方法,AOT会损失动态能力,如果编译需要额外处理,需要提前告知GraalVM未来会反射调用哪些方法或构造器,例如springboot就提供了一些注解,保证AOT编译时功能正常,但不是所有框架都像Spring那样适配了AOT。
-
配置文件不能放进可执行文件,也需要额外处理,程序代码可改为相对路径读取。