跳至主要內容

win10 安装使用 graalvm 的 native-image 功能,并成功运行 springboot 示例

Mr.Chen大约 6 分钟文章JavaGraalvmSpringBoot

GraalVM
GraalVM

一、下载安装GraalVM

https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.3.1open in new window

GraalVM Community Edition
GraalVM Community Edition

我下载的是当前最新的GraalVM Community Edition 22.3.1,选择的是Java 17。

下载好之后解压到本地随便一个目录(比如:D:\software\Java\graalvm-ce-java17-22.3.1),并配置环境变量Path。

打开命令提示符,进入到jdk的bin目录,通过gu命令安装native-image。

C:\Users\Think>D:

D:\>cd software\Java\graalvm-ce-java17-22.3.1\bin

D:\software\Java\graalvm-ce-java17-22.3.1\bin>gu install native-image

安装完之后可以通过gu list命令查看是否成功安装

D:\software\Java\graalvm-ce-java17-22.3.1\bin>gu list
ComponentId              Version             Component name                Stability                     Origin
---------------------------------------------------------------------------------------------------------------------------------

graalvm                  22.3.1              GraalVM Core                  Supported
native-image             22.3.1              Native Image                  Early adopter                 github.com

二、安装Microsoft Visual Studio

windows系统上要正常运行native-image,必须安装MSVC,否则会报以下错误。

Default native-compiler executable 'cl.exe' not found via environment variab

或者以下错误

Error compiling query code (in C:\Users\xxx\AppData\Local\Temp\SVM-8246985

我安装的是2019版的,下载地址是

https://my.visualstudio.com/Downloads?q=visual studio 2019&wt.mc_id=o~msft~vscom~older-downloadsopen in new window

download visualstudio
download visualstudio

选择社区版即可,下载完之后就可以安装了,有些教程是说仅仅安装MSVC单组件即可,但是我贪方便,直接安装了C++桌面开发。

install visualstudio
install visualstudio

安装完之后提示要重启系统,不知道不重启会怎样,反正我是重启了。

接着需要配置三个环境变量

Path=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64

(这个是解决cl.exe' not found错误的)

LIB=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\um\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.19041.0\ucrt\x64;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\lib\x64;
INCLUDE=C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include;

(这是解决Error compiling query code错误的)

要注意的是,这些文件路径带有版本号,以实际为准

三、运行springboot示例代码

如果自己已经有springboot项目,可以直接修改,为了直观,直接用springboot示例代码,比较直观,有问题也能快速排查。

从spring官网可以根据要求定制示例代码。

https://start.spring.io/open in new window

springboot
springboot

我只选择了GraalVM Native Support和Spring Web,只要能跑起来就可以。选完之后按"GENERATE"按钮即可下载。

下载后解压到本地随意目录(比如:D:\workspace\project\springboot-native)。

打开命令提示符,进到项目目录,敲上以下命令就可以直接构建springboot可直接运行文件。

D:\software\Java\graalvm-ce-java17-22.3.1\bin>cd D:\workspace\project\springboot-native
D:\workspace\project\springboot-native>gradlew nativeCompile

顺便把结果贴一下,以便参考

> Task :nativeCompile
[native-image-plugin] GraalVM Toolchain detection is disabled
[native-image-plugin] GraalVM location read from environment variable: JAVA_HOME
[native-image-plugin] Native Image executable path: D:\software\Java\graalvm-ce-java17-22.3.1\bin\native-image.cmd
=======================================================================================================================
GraalVM Native Image: Generating 'demo' (executable)...
========================================================================================================================
[1/7] Initializing...                                                                                   (17.6s @ 0.19GB
 Version info: 'GraalVM 22.3.1 Java 17 CE'
 Java version info: '17.0.6+10-jvmci-22.3-b13'
 C compiler: cl.exe (microsoft, x64, 19.29.30148)
 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.format.support.DefaultFormattingConversionService#jsr354Present set to false 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.boot.logging.log4j2.Log4J2LoggingSystem$Factory#PRESENT set to false at build time
Field org.springframework.boot.logging.logback.LogbackLoggingSystem$Factory#PRESENT set to true at build time
Field org.springframework.boot.logging.java.JavaLoggingSystem$Factory#PRESENT set to true 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.web.context.request.RequestContextHolder#jsfPresent set to false at build timed time
Field org.springframework.web.servlet.view.InternalResourceViewResolver#jstlPresent set to false at build time
Field org.springframework.http.converter.json.Jackson2ObjectMapperBuilder#jackson2XmlPresent 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.boot.autoconfigure.web.format.WebConversionService#JSR_354_PRESENT 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.context.event.ApplicationListenerMethodAdapter#reactiveStreamsPresent 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
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...  [*********]                                                              (106.1s @ 2.23GB
  15,266 (92.64%) of 16,478 classes reachable
  24,944 (67.69%) of 36,848 fields reachable
  73,664 (62.39%) of 118,077 methods reachable
     798 classes,   242 fields, and 3,537 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...                                                                              (14.3s @ 1.62GB
[4/7] Parsing methods...      [***]                                                                      (9.1s @ 2.81GB
[5/7] Inlining methods...     [***]                                                                      (5.4s @ 1.76GB
[6/7] Compiling methods...    [********]                                                                (74.8s @ 1.67GB)
[7/7] Creating image...                                                                                 (10.8s @ 3.69GB
  34.48MB (52.40%) for code area:    48,251 compilation units
  30.89MB (46.94%) for image heap:  352,399 objects and 120 resources
 441.67KB ( 0.66%) for other data
  65.80MB in total

------------------------------------------------------------------------------------------------------------------------

Top 10 packages in code area:                               Top 10 object types in image heap
   1.64MB sun.security.ssl                                     7.34MB byte[] for code metadata
   1.05MB java.util                                            3.63MB java.lang.Class
 842.84KB java.lang.invoke                                     3.40MB java.lang.String
 725.07KB com.sun.crypto.provider                              2.84MB byte[] for general heap data
 563.66KB org.apache.catalina.core                             2.80MB byte[] for java.lang.String
 521.32KB org.apache.tomcat.util.net                           1.28MB com.oracle.svm.core.hub.DynamicHubCompanion
 496.14KB org.apache.coyote.http2                              1.02MB byte[] for embedded resources
 477.32KB java.lang                                          821.19KB byte[] for reflection metadata
 470.10KB c.s.org.apache.xerces.internal.impl.xs.traversers  660.87KB java.lang.String[]
 467.51KB java.util.concurrent                               616.78KB java.util.HashMap$Node
  26.98MB for 622 more packages                                5.63MB for 3062 more object types
-----------------------------------------------------------------------------------------------------------------------

                        8.9s (3.5% of total time) in 38 GCs | Peak RSS: 5.83GB | CPU load: 5.40
------------------------------------------------------------------------------------------------------------------------

Produced artifacts
 D:\workspace\project\springboot-native\build\native\nativeCompile\demo.build_artifacts.txt (txt)
 D:\workspace\project\springboot-native\build\native\nativeCompile\demo.exe (executable)
========================================================================================================================

Finished generating 'demo' in 4m 12s.
[native-image-plugin] Native Image written to: D:\workspace\project\springboot-native\build\native\nativeCompile

BUILD SUCCESSFUL in 4m 21s
9 actionable tasks: 1 executed, 8 up-to-date

成功之后,就可以在build\native\nativeCompile目录看到可执行文件

nativeCompile
nativeCompile

直接双击demo.exe即可运行

效果图
效果图

全篇就到此结束了。。。。

当然,还有另外一种方式,先构建jar包,然后再用native-image命令编译成可执行文件。

D:\workspace\project\springboot-native>gradlew build
D:\workspace\project\springboot-native>cd build\libs
D:\workspace\project\springboot-native\build\libs>native-image -jar demo-0.0.1-SNAPSHOT.jar

这样也是可以的。

最终打出来的exe文件有65M,也不小,jar包的话也就18M,不过exe不需要jvm环境,并且启动后占用60M内存,而直接启动jar文件占用109M内存,相对来说还是有优势。