聊聊 Java 与原生,尝尝 GraalVM 与 Quarkus - 向云原生靠近

发布时间:2025-12-10 11:24:59 浏览次数:11

本人资历、水平有限,如有错误请大佬们批评指正,谢谢!

文章目录

  • 前言
    • 基于 JVM 的应用启动比原生应用慢一拍
    • 运行期间性能不差,启动笨重一点又怎么样?
  • 环境准备
    • 本文环境概览
    • 准备 GraalVM
  • 初尝 GraalVM 的 Native Image
    • GraalVM 这名字听起来像是新研发的虚拟机?
    • hello, world 的 Native Image
      • native-image 使用方法
      • 构建 hello, world
      • 关于 NativeImageBuildServer 与构建过程资源占用
    • Native Image 使用没有限制吗?肯定有
      • 动态类加载、反射、动态代理、JNI、JCA 等特性在部分场景需要配置
        • 已知类的反射可以正常执行
      • 封闭优化不支持的特性
        • invokedynamic(部分支持)
        • Serialization(序列化,需要通过配置才能支持)
        • Security Manager(安全管理)
      • 部分特性在 SVM 的实现会有所差异
        • Class Initializers
        • 不再调用 finalize() 方法
        • SVM 未实现 java.lang.Thread 中的废弃方法
        • Unsafe 相关
      • 尝试构建 Spring Boot 项目的 Native Image
        • 默认参数构建出 Fallback Image
        • 指定不使用 Fallback Image
        • 指定运行时才报告错误
        • 基于 class 文件和指定 classpath 构建 Native Image
  • Quarkus - Supersonic Subatomic Java
    • 称为 “超声波 Java” 的 Quarkus 有什么特性?
      • CONTAINER FIRST(容器优先)
      • UNIFIES IMPERATIVE AND REACTIVE(统一命令式和响应式编程)
      • DEVELOPER JOY(开发者友好)
      • BEST OF BREED LIBRARIES AND STANDARDS(基于最好的库和标准)
    • 说这么多,不如试试
      • 初始化 Quarkus 项目
      • 数据库准备
      • 基于 Spring 体系的 CRUD 代码
      • 在 Dev 模式运行验证
        • dev 模式下支持 Hot Reload
      • 构建 Native Image
  • 参考资料

前言

基于 JVM 的应用启动比原生应用慢一拍

平时 Java 用得比较多,也会用 Golang 或者 C 等静态编译语言的人,应该多少都会感觉到,即使是最简单的 hello, world,Java 程序的启动速度相比静态编译出的可执行程序会慢上一拍。
如果使用 Java 等语言实现的运行在 JVM 上的 CLI 工具,这种慢一拍的感觉应该会更明显(使用过 RocketMQ 的 mqadmin 脚本的同学应该有所体会)。
Spring Framework 全家桶的启动就更不用说了,大项目启动时间可达 分钟 级别……

先来个简单的实验:

一段 Java 的 hello, world

public class Main {public static void main(String[] args) {System.out.println("hello, java");}}

一段 Golang 的 hello, world

package mainfunc main() {println("hello, go")}➜ ~ go build main.go➜ ~ repeat 10 time ./mainhello, go./main 0.00s user 0.00s system 107% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 118% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 110% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 109% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 112% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 119% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 109% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 108% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 106% cpu 0.001 totalhello, go./main 0.00s user 0.00s system 107% cpu 0.001 total➜ ~ javac Main.java ➜ ~ repeat 10 time java Mainhello, javajava Main 0.07s user 0.04s system 119% cpu 0.087 totalhello, javajava Main 0.07s user 0.02s system 115% cpu 0.074 totalhello, javajava Main 0.06s user 0.01s system 114% cpu 0.063 totalhello, javajava Main 0.06s user 0.01s system 146% cpu 0.046 totalhello, javajava Main 0.06s user 0.01s system 147% cpu 0.049 totalhello, javajava Main 0.05s user 0.02s system 142% cpu 0.046 totalhello, javajava Main 0.05s user 0.01s system 143% cpu 0.045 totalhello, javajava Main 0.05s user 0.01s system 142% cpu 0.045 totalhello, javajava Main 0.05s user 0.02s system 144% cpu 0.045 totalhello, javajava Main 0.05s user 0.01s system 142% cpu 0.045 total

Golang 写的 hello, world 基本是 敲下键盘那一刻就已经运行完毕退出了,Java 写的 hello, world 运行时间人类可以感受到,尤其是冷启动(首次启动 JVM 进程,可能长达数百毫秒。在树莓派这类硬件上,JVM 冷启动可长达数秒)。

运行期间性能不差,启动笨重一点又怎么样?

基于 JVM 的应用确实需要一定的启动时间(尤其是 Spring),启动内存相比原生应用也不低。“速度慢,吃内存” 成了大家黑 Java 的关键点。

不过,在目前常见的架构下,这些问题不会特别突出:

  • 在应用运行期间,因 JVM 的各种优化手段,应用的运行性能会逐渐优化,不会比原生应用差。
  • 在内存方面,JVM 所需内存对于一般服务器也没有什么压力。
  • 启动慢的问题,在有滚动发布机制的环境中,应用多花一点时间进入就绪状态也没什么问题。

这么看来其实 “速度慢,吃内存” 也不是什么问题。

但是, 脱离场景谈技术都是耍流氓

对于一些用户群体比较确定、不会有突发流量,充分评估过资源需求、本身比较稳定的应用,启动时间和内存占用一般不会有什么问题。

但是对于弹性计算、存在突发流量等需要时刻准备水平扩容的场景,JVM 的短板就被放大了。

例如基于事件驱动的函数计算,按需分配资源,不用的时候不占用资源。不预留实例的函数计算,只有事件发生的时候才会分配资源并创建实例。

从以下三个方面谈 JVM 的短板:

  • 在启动时间方面:
    如果函数实例是后台计算等不涉及用户体验的操作,实例启动慢一点影响不会很大。
    但如果函数提供的服务具有即时性、涉及用户体验、对时间敏感,实例启动时间就会在很大程度上影响着用户体验。原生应用和 JVM 相比,本身就没有启动的过程(本人的理解,从另一个角度说,操作系统的启动就是原生应用的启动)。因应用经过静态编译,业务逻辑的启动一般也不会占用太多时间(除非涉及 I/O 等对于 CPU 来说很慢的操作)。

  • 在内存占用方面:
    例如使用阿里云函数计算服务,内存需求关系到费用问题。一般虚拟机和原生应用相比在内存占用方面没有优势。一段相同逻辑的代码分别使用虚拟机和原生应用运行,虚拟机内存需求一般不会低于原生应用。

  • 在运行期间:
    JVM 有很多优化手段,基于 JVM 的应用经过时间的推移或者主动进行预热,可能会越来越快。但是,在弹性计算这类场景中,JVM 可能根本来不及优化,实例就已经被释放了。没有经过优化的 JVM 应用在运行速度上很难和原生应用的机器语言匹敌。

  • 所以,回答标题的问题:

    在现在这种新架构、新技术百花齐放的时代,如果 JVM 相关技术栈不能与时俱进,将很容易被后来者蚕食。


    环境准备

    本文环境概览

    有条件的建议在 Linux 进行,Windows 上进行可能坑会稍多。

    准备 GraalVM

    GraalVM 可以在 Oracle 官网下载:https://www.oracle.com/downloads/graalvm-downloads.html?selected_tab=20l
    注意版本的选择!

    国内网络环境下载速度可能较慢,此处提供本人在用的版本:

    • GraalVM EE Linux 20.1.0 https://wuweijie.oss-cn-shenzhen.aliyuncs.com/resources/graalvm-ee-java11-linux-amd64-20.1.0.tar.gz
    • GraalVM EE Native Image Linux 20.1.0 组件离线安装包 (下载免C币) https://download.csdn.net/download/wu_weijie/12490465

    GraalVM 的安装使用和普通的 JDK 没有区别,下载后解压并设置环境变量就可以了。

    GraalVM 相比普通的 OpenJDK / Oracle JDK 增加了一些命令,例如用于管理 GraalVM 组件的命令 gu。

    不要忘记安装 Native Image 组件!可以通过 gu 命令安装提前下载好 Native Image 组件的 jar。
    Native Image 组件安装文档:https://docs.oracle.com/en/graalvm/enterprise/20/guide/reference/native-image.html

    ➜ ~ javac -versionjavac 11.0.7➜ ~ java -version java version "11.0.7" 2020-04-14 LTSJava(TM) SE Runtime Environment GraalVM EE 20.1.0 (build 11.0.7+8-LTS-jvmci-20.1-b02)Java HotSpot(TM) 64-Bit Server VM GraalVM EE 20.1.0 (build 11.0.7+8-LTS-jvmci-20.1-b02, mixed mode, sharing)➜ ~ native-image Please specify options for native-image building or use --help for more info.

    环境基本准备好了!

    使用 Native Image 可能还需要 gcc 等开发工具,各环境所需依赖可以参考 Quarkus 文档:
    https://quarkus.io/guides/building-native-image#prerequisites


    初尝 GraalVM 的 Native Image

    除了 Native Image,GraalVM 还有很多黑科技。篇幅有限,本文只关注 Native Image。

    官网:https://www.graalvm.org/

    GraalVM 这名字听起来像是新研发的虚拟机?

    UNIFIES IMPERATIVE AND REACTIVE(统一命令式和响应式编程)

    无论是使用命令式还是响应式编程,都有相近的代码风格

    命令式:

    @InjectSayService say;@GET@Produces(MediaType.TEXT_PLAIN)public String hello() {return say.hello();}

    响应式:

    @Inject @Channel("kafka")Publisher<String> reactiveSay;@GET@Produces(MediaType.SERVER_SENT_EVENTS)public Publisher<String> stream() {return reactiveSay;}

    DEVELOPER JOY(开发者友好)

  • Quarkus 统一了各种不同的技术框架的配置
  • Quarkus 在开发模式下可以实现保存代码即运行,而且开箱即用,无需额外配置
  • Quarkus 支持各类构建工具,Maven, Gradle 或者 IDE
  • Quarkus 将尽量统一开发的方式与风格
  • BEST OF BREED LIBRARIES AND STANDARDS(基于最好的库和标准)

    Quarkus 不会让用户花费大量时间学习新技术,其编程模型建立在各种已有的标准之上,例如:

    • JPA
    • Spring
    • JTA
    • Vert.x
    • CDI
    • JAX-RS
    • Apache Camel

    说这么多,不如试试

    初始化 Quarkus 项目

    Quarkus 提供了一个类似于 Spring Initializr 的项目初始化方式:https://code.quarkus.io/

    任选一种初始化方式:

    • 在 https://code.quarkus.io/ 完成初始化并下载项目
    • 在 IntelliJ IDEA 创建 Quarkus 项目(推荐,封装了 code.quarkus.io)

    以下操作基于 IntelliJ IDEA。

    可选构建工具:

    • Maven
    • Gradle (Preview)

    选择依赖:

    • RESTEasy JAX-RS 默认选择
    • 数据库相关
    • Spring 相关(Preview 阶段,选来体验一下)

    项目初始化后且依赖下载完成后,可以使用 ./mvnw compile quarkus:dev 运行项目,或者通过 GUI:

    Quarkus 启动:

    在浏览器打开 http://localhost:8080/

    项目初始化完成。

    数据库准备

    create table t_order(id bigserial not nullconstraint t_order_pkprimary key,order_time timestamp default CURRENT_TIMESTAMP not null,person_name varchar default ''::character varying not null,order_type varchar default 'None'::character varying not null,remark varchar);alter table t_order owner to postgres;INSERT INTO public.t_order (id, order_time, person_name, order_type, remark) VALUES (1, '2020-06-06 16:31:16.000000', '烫烫烫', 'None', null);INSERT INTO public.t_order (id, order_time, person_name, order_type, remark) VALUES (2, '2020-06-06 16:31:51.000000', '锟斤拷', 'Dinner', 'Double');

    基于 Spring 体系的 CRUD 代码

    Quarkus 提供了 Spring 的兼容。

    Order.java 节选,忽略 getter / setter:

    package vip.wuweijie.hello.quarkus.entity;import javax.persistence.*;import java.io.Serializable;import java.sql.Timestamp;/*** @author wuweijie*/@Entitypublic class Order implements Serializable {@Idprivate Long id;@Column(insertable = false)private Timestamp orderTime;private String personName;private String orderType;private String remark;}

    OrderRepository.java:

    package vip.wuweijie.hello.quarkus.repository;import org.springframework.data.jpa.repository.JpaRepository;import vip.wuweijie.hello.quarkus.entity.Order;/*** @author wuweijie*/public interface OrderRepository extends JpaRepository<Order, Long> {}

    OrderResource.java

    package vip.wuweijie.hello.quarkus;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import vip.wuweijie.hello.quarkus.entity.Order;import vip.wuweijie.hello.quarkus.repository.OrderRepository;import java.util.List;/*** @author wuweijie*/@RestController@RequestMapping("/order")public class OrderResource {@Autowiredprivate OrderRepository orderRepository;@GetMappingpublic List<Order> getOrders() {return orderRepository.findAll();}@PostMappingpublic Order addOrder(@RequestBody Order order) {return orderRepository.saveAndFlush(order);}}

    在 Dev 模式运行验证

    请求:

    GET http://localhost:8080/order###POST http://localhost:8080/orderContent-Type: application/json{"orderTime": 1591432276000,"personName": "POST","orderType": "nil","remark": "From Post"}

    先执行一次查询:

    GET http://localhost:8080/orderHTTP/1.1 200 OKContent-Length: 287Content-Type: application/json[{"id": 1,"orderTime": 1591432276000,"personName": "烫烫烫","orderType": "None","remark": null},{"id": 2,"orderTime": 1591432311000,"personName": "锟斤拷","orderType": "Dinner","remark": "Double"}]

    执行一次插入,返回数据:

    {"id":3,"orderTime":1591432276000,"personName":"POST","orderType":"nil","remark":"From Post"}

    再次查询数据:

    GET http://localhost:8080/orderHTTP/1.1 200 OKContent-Length: 287Content-Type: application/json[{"id": 1,"orderTime": 1591432276000,"personName": "烫烫烫","orderType": "None","remark": null},{"id": 2,"orderTime": 1591432311000,"personName": "锟斤拷","orderType": "Dinner","remark": "Double"},{"id": 3,"orderTime": 1591434989319,"personName": "POST","orderType": "nil","remark": "From Post"}]

    dev 模式下支持 Hot Reload

    如果检测到代码文件变化,则会重新加载代码:

    2020-06-06 17:16:28,560 INFO [io.qua.dep.dev] (vert.x-worker-thread-1) Changed source files detected, recompiling [/home/sia/IdeaProjects/hello-quarkus/src/main/java/vip/wuweijie/hello/quarkus/entity/Order.java]2020-06-06 17:16:28,950 INFO [io.quarkus] (Quarkus Main Thread) hello-quarkus stopped in 0.030s__ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ 2020-06-06 17:16:29,130 INFO [io.qua.arc.pro.BeanProcessor] (build-26) Found unrecommended usage of private members (use package-private instead) in application beans:- @Inject field vip.wuweijie.hello.quarkus.OrderResource#orderRepository2020-06-06 17:16:29,220 INFO [io.agr.pool] (Quarkus Main Thread) Datasource '<default>': Initial size smaller than min. Connections will be created when necessary2020-06-06 17:16:29,258 INFO [io.quarkus] (Quarkus Main Thread) hello-quarkus 1.0-SNAPSHOT on JVM (powered by Quarkus 1.5.0.Final) started in 0.301s. Listening on: http://0.0.0.0:80802020-06-06 17:16:29,259 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.2020-06-06 17:16:29,259 INFO [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, mutiny, narayana-jta, resteasy, resteasy-jackson, spring-boot-properties, spring-data-jpa, spring-di, spring-web]2020-06-06 17:16:29,259 INFO [io.qua.dep.dev] (vert.x-worker-thread-1) Hot replace total time: 0.700s

    构建 Native Image

    本示例 建议可用内存不小于 8GB ,依赖越多,构建过程所需内存越大。

    执行命令

    ./mvnw package -Pnative

    执行日志:

    ➜ hello-quarkus git:(master) ✗ ./mvnw package -Pnative[INFO] Scanning for projects...[INFO] [INFO] --------------< vip.wuweijie.hello.quarkus:hello-quarkus >--------------[INFO] Building hello-quarkus 1.0-SNAPSHOT[INFO] --------------------------------[ jar ]---------------------------------[INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello-quarkus ---[INFO] Using 'UTF-8' encoding to copy filtered resources.[INFO] Copying 2 resources[INFO] [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ hello-quarkus ---[INFO] Changes detected - recompiling the module![INFO] Compiling 4 source files to /home/sia/IdeaProjects/hello-quarkus/target/classes[INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello-quarkus ---[INFO] Using 'UTF-8' encoding to copy filtered resources.[INFO] skip non existing resourceDirectory /home/sia/IdeaProjects/hello-quarkus/src/test/resources[INFO] [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ hello-quarkus ---[INFO] Changes detected - recompiling the module![INFO] Compiling 2 source files to /home/sia/IdeaProjects/hello-quarkus/target/test-classes[INFO] [INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ hello-quarkus ---[INFO] [INFO] -------------------------------------------------------[INFO] T E S T S[INFO] -------------------------------------------------------[INFO] Running vip.wuweijie.hello.quarkus.ExampleResourceTest2020-06-06 17:28:56,229 INFO [io.qua.arc.pro.BeanProcessor] (build-4) Found unrecommended usage of private members (use package-private instead) in application beans:- @Inject field vip.wuweijie.hello.quarkus.OrderResource#orderRepository2020-06-06 17:28:57,057 INFO [io.agr.pool] (main) Datasource '<default>': Initial size smaller than min. Connections will be created when necessary2020-06-06 17:28:57,446 INFO [io.quarkus] (main) Quarkus 1.5.0.Final on JVM started in 2.301s. Listening on: http://0.0.0.0:80812020-06-06 17:28:57,447 INFO [io.quarkus] (main) Profile test activated. 2020-06-06 17:28:57,447 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, mutiny, narayana-jta, resteasy, resteasy-jackson, spring-boot-properties, spring-data-jpa, spring-di, spring-web][INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.775 s - in vip.wuweijie.hello.quarkus.ExampleResourceTest2020-06-06 17:28:58,615 INFO [io.quarkus] (main) Quarkus stopped in 0.034s[INFO] [INFO] Results:[INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0[INFO] [INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello-quarkus ---[INFO] Building jar: /home/sia/IdeaProjects/hello-quarkus/target/hello-quarkus-1.0-SNAPSHOT.jar[INFO] [INFO] --- quarkus-maven-plugin:1.5.0.Final:build (default) @ hello-quarkus ---[INFO] [org.jboss.threads] JBoss Threads version 3.1.1.Final[INFO] [org.hibernate.Version] HHH000412: Hibernate ORM core version 5.4.16.Final[INFO] [io.quarkus.arc.processor.BeanProcessor] Found unrecommended usage of private members (use package-private instead) in application beans:- @Inject field vip.wuweijie.hello.quarkus.OrderResource#orderRepository[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building native image source jar: /home/sia/IdeaProjects/hello-quarkus/target/hello-quarkus-1.0-SNAPSHOT-native-image-source-jar/hello-quarkus-1.0-SNAPSHOT-runner.jar[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Building native image from /home/sia/IdeaProjects/hello-quarkus/target/hello-quarkus-1.0-SNAPSHOT-native-image-source-jar/hello-quarkus-1.0-SNAPSHOT-runner.jar[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Running Quarkus native-image plugin on GraalVM Version 20.1.0 (Java Version 11.0.7)[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] /usr/local/graalvm-ee-java11-20.1.0/bin/native-image -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-DCoordinatorEnvironmentBean.transactionStatusManagerEnable=false -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=1 -J-Duser.language=en -J-Dfile.encoding=UTF-8 --initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime -H:+JNI -jar hello-quarkus-1.0-SNAPSHOT-runner.jar -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:-IncludeAllTimeZones -H:EnableURLProtocols=http,https --enable-all-security-services -H:NativeLinkerOption=-no-pie --no-server -H:-UseServiceLoaderFeature -H:+StackTrace hello-quarkus-1.0-SNAPSHOT-runner-H:IncludeAllTimeZones and -H:IncludeTimeZones are now deprecated. Native-image includes all timezonesby default.[hello-quarkus-1.0-SNAPSHOT-runner:9103] classlist: 6,932.73 ms, 1.19 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] (cap): 541.19 ms, 1.68 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] setup: 2,467.68 ms, 1.68 GB17:29:11,362 INFO [org.hib.Version] HHH000412: Hibernate ORM core version 5.4.16.Final17:29:11,367 INFO [org.hib.ann.com.Version] HCANN000001: Hibernate Commons Annotations {5.1.0.Final}17:29:11,384 INFO [org.hib.dia.Dialect] HHH000400: Using dialect: io.quarkus.hibernate.orm.runtime.dialect.QuarkusPostgreSQL10Dialect17:29:23,231 INFO [org.jbo.threads] JBoss Threads version 3.1.1.FinalWARNING GR-10238: VarHandle for static field is currently not fully supported. Static field private static volatile java.lang.System$Logger jdk.internal.event.EventHelper.securityLogger is not properly marked for Unsafe access![hello-quarkus-1.0-SNAPSHOT-runner:9103] (clinit): 873.00 ms, 5.41 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] (typeflow): 21,272.04 ms, 5.41 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] (objects): 26,923.87 ms, 5.41 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] (features): 1,099.55 ms, 5.41 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] analysis: 53,824.27 ms, 5.41 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] universe: 1,649.18 ms, 5.41 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] (parse): 4,248.05 ms, 5.59 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] (inline): 2,953.33 ms, 5.79 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] (compile): 61,356.01 ms, 7.23 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] compile: 72,475.76 ms, 7.23 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] image: 5,032.36 ms, 7.23 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] write: 995.36 ms, 7.23 GB[hello-quarkus-1.0-SNAPSHOT-runner:9103] [total]: 143,635.77 ms, 7.23 GB[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 145589ms[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 02:34 min[INFO] Finished at: 2020-06-06T17:31:25+08:00[INFO] ------------------------------------------------------------------------

    构建完成后,target 目录下多了一个可执行文件。

    执行后,可以看到应用的启动时间只需要 0.043s,基于 JVM 启动需要 1.730s


    参考资料

    GraalVM 相关:

    • https://docs.oracle.com/en/graalvm/enterprise/20/guide/index.html
    • https://github.com/oracle/graal/blob/master/substratevm/LIMITATIONS.md
    • https://github.com/oracle/graal/blob/master/substratevm/CONFIGURE.md
    • https://github.com/oracle/graal/blob/master/substratevm/REFLECTION.md

    Quarkus 相关:

    • https://quarkus.io/assets/images/quarkus_metrics_graphic_bootmem_wide.png
    • https://quarkus.io/
    • https://quarkus.io/vision/container-first
    • https://quarkus.io/vision/standards
    • https://quarkus.io/vision/developer-joy
    • https://quarkus.io/vision/continuum
    • https://quarkus.io/guides/building-native-image
    需要做网站?需要网络推广?欢迎咨询客户经理 13272073477