首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >GraalVM(云原生时代的Java)和IoT在边缘侧落地与实践

GraalVM(云原生时代的Java)和IoT在边缘侧落地与实践

作者头像
sanshengshui
发布于 2023-05-01 02:01:14
发布于 2023-05-01 02:01:14
1.3K00
代码可运行
举报
文章被收录于专栏:穆书伟穆书伟
运行总次数:0
代码可运行

环顾四周,皆是对手!

  • 云时代的掉队者,由于Java启动的高延时、对资源的高占用、导致在ServerlessFaaS架构下力不从心,在越来越流行的边缘计算、IoT方向上也是难觅踪影;
  • Java语言在业务服务开发中孤独求败,但在系统级应用领域几乎是C、C++、搅局者Go、黑天鹅Rust的天下;
  • 移动应用、敏捷应用的追随者,移动应用中Android逐步去Java,前端又是JS的世界,敏捷开发方面前有Ruby、Python后有NodeJS;

此时众多的Javaer会不经意发问:学Java还有未来么?

你可以嫌弃Java, 但是可以永远相信JVM! 在云原生如日中天、Serverless日渐成熟、新语言百花齐放的当下,跨语言、Native支持、高性能低资源占用的技术必定是其璀璨的明珠,而GraalVM正是这样一个承载了JVM未来,将Java带入下一波技术的弄潮儿。

GraalVM - 云原生时代的Java

“一次编写,到处运行“是Java语言的特性,这一重要特性依靠的是JVM虚拟机

在讨论GraalVM之前,我们先聊下Java代码是怎么运行的?

从硬件视角来看,Java字节码无法直接执行。因此,Java虚拟机需要将字节码翻译成机器码。

从虚拟机视角来看,执行Java代码首先需要将它编译而成的 class 文件加载到 Java 虚拟机中。加载后的 Java 类会被存放于方法区(Method Area)中。实际运行时,虚拟机会执行方法区内的代码。Java 虚拟机同样也在内存中划分出堆和栈来存储运行时数据。

不同的是,Java 虚拟机会将栈细分为面向 Java 方法的 Java 方法栈,面向本地方法(用 C++ 写的 native 方法)的本地方法栈,以及存放各个线程执行位置的 PC 寄存器。

在运行过程中,每当调用进入一个 Java 方法,Java 虚拟机会在当前线程的 Java 方法栈中生成一个栈帧,用以存放局部变量以及字节码的操作数。这个栈帧的大小是提前计算好的,而且 Java 虚拟机不要求栈帧在内存空间里连续分布。

当退出当前执行的方法时,不管是正常返回还是异常返回,Java 虚拟机均会弹出当前线程的当前栈帧,并将之舍弃。

GraalVM带来哪些神奇的黑魔法🧙‍♂️

  1. 更快、更轻量化的应用 GraalVM的高性能JIT编译器可以生成优化的本地机器代码,由于采用了先进的编译器优化和积极复杂的内联技术,运行速度更快,产生的垃圾更少,使用的CPU更少。最终的结果是应用程序运行速度更快,消耗的资源更少,从而降低了云和基础设施的成本。
  2. Ahead-Of-Time(AOT)提前编译技术 AOT 提前编译,是相对于即时编译而言的。AOT在运行过程中耗费 CPU 资源来进行即时编译,而程序也能够在启动的瞬间就达到理想的性能。例如 C 和 C++语言采用的是AOT静态编译,直接将代码转换成机器码执行。而 Java 一直采用的是解释 + 即时编译技术。 GraalVM 的 AOT 编译实际上是借助了 SubstrateVM 编译框架,可以将 SubstrateVM 理解为一个内嵌精简版的 JVM,包含异常处理,同步,线程管理,内存管理(垃圾回收)和 JNI 等组件。 SubstrateVM 的启动时间非常短,内存开销非常少。用这种方式编译出的 Java 程序的执行时间可与C语言持平。
  3. 语言互操作性 Graal VM 被官方称为“Universal VM”和“Polyglot VM”,这是一个在 HotSpot 虚拟机基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台使用,这里“任何语言”包括了 Java、Scala、Groovy、Kotlin 等基于 Java 虚拟机之上的语言,还包括了 C、C++、Rust 等基于 LLVM 的语言,同时支持其他像 JavaScript、Ruby、Python 和 R 语言等等。Graal VM 可以无额外开销地混合使用这些编程语言,支持不同语言中混用对方的接口和对象,也能够支持这些语言使用已经编写好的本地库文件。

GraalVM在IoT边缘侧实现落地,效果显著!

1、安装无需JVM环境,30000行项目安装仅需16M内存占用,可在mac、linux-arm64、windows和树莓派等硬件环境上运行;

2、项目启动时间节省99%, 仅需10ms!享受极速的软件体验;

安装

GraalVM在 SDKMAN上有多个版本,可通过sdk list java进行查看,我这里使用的是22.2 社区版本

安装SDKMAN!, 请看安装文档

sdk install java 22.2.r11-grl

上述GraalVM安装完成后,需要Native Image组件,使用下述命令行进行安装:

Native Image安装

gu install native-image

Maven项目设置

详细graalvm-maven-plugin使用简介见:https://graalvm.github.io/native-build-tools/latest/maven-plugin-quickstart.html

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<profile>
            <id>native</id>
            <activation>
                <property>
                    <name>native</name>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.graalvm.buildtools</groupId>
                        <artifactId>native-maven-plugin</artifactId>
                        <version>${graalvm-buildtools.version}</version>
                        <extensions>true</extensions>
                        <executions>
                            <execution>
                                <id>build-native</id>
                                <goals>
                                    <goal>compile-no-fork</goal>
                                </goals>
                                <phase>package</phase>
                            </execution>
                        </executions>
                        <configuration>
                            <skip>false</skip>
                            <imageName>${appName}</imageName>
                            <requiredVersion>${graalvm.version}</requiredVersion>
                            <mainClass>${mainClass}</mainClass>
                            <buildArgs>
                                <arg>--no-fallback</arg>
                                <arg>-Dfile.encoding=UTF-8</arg>
                                <arg>-H:-CheckToolchain</arg>
                                <arg>-H:+ReportExceptionStackTraces</arg>
                            </buildArgs>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

当然GraalVM的 AOT提前编译技术也不是完全没有缺点,其对于多语言、反射和字节码动态加载技术需要相对繁琐的配置。

src/main/resources文件夹下有

  • native-image.properties //native image配置信息文件
  • reflection-config.json //native 需要反射的类配置文件

具体配置信息详情见: https://www.graalvm.org/22.0/reference-manual/native-image/Reflection/#manual-configuration

native-image.properties信息如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Args = -H:ReflectionConfigurationResources=${.}/reflection-config.json \
       -H:IncludeLocales=zh,en,de,fr \
       --initialize-at-run-time=io.netty.buffer.AbstractReferenceCountedByteBuf \
       --initialize-at-run-time=io.netty.buffer.ByteBufAllocator \
       --initialize-at-run-time=io.netty.buffer.ByteBufUtil \
       --initialize-at-run-time=io.netty.buffer.ByteBufUtil$HexUtil \
       --initialize-at-run-time=io.netty.buffer.PooledByteBufAllocator \
       --initialize-at-run-time=io.netty.buffer.UnpooledHeapByteBuf \
       --initialize-at-run-time=io.netty.buffer.UnreleasableByteBuf \
       --initialize-at-run-time=io.netty.util.AbstractReferenceCounted \
       --initialize-at-run-time=io.netty.util.internal.ThreadLocalRandom \
       --initialize-at-run-time=io.netty.util.concurrent.GlobalEventExecutor \
       --initialize-at-run-time=io.netty.util.concurrent.ImmediateEventExecutor \
       --initialize-at-run-time=io.netty.util.concurrent.ScheduledFutureTask \
       -Dio.netty.noUnsafe=true \
       -Dio.netty.leakDetection.level=DISABLED

reflection-config.json信息如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[
  {
    "name": "io.netty.channel.socket.nio.NioSocketChannel",
    "methods": [
      { "name": "<init>", "parameterTypes": [] }
    ]
  },
......
{
    "name" : "iot.technology.client.toolkit.nb.service.mobile.domain.action.data.MobCachedCommandResponse",
    "allDeclaredMethods" : true,
    "allPublicMethods" : true,
    "allDeclaredClasses" : true,
    "allPublicClasses" : true,
    "allDeclaredConstructors" : true,
    "allPublicConstructors" : true
  }
]

上述信息配置完成,我们在项目根目录下执行以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mvn clean package -Pnative

会见到下面的日志命令输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[INFO] --- native-maven-plugin:0.9.17:compile-no-fork (build-native) @ toolkit-app ---
[INFO] Found GraalVM installation from JAVA_HOME variable.
......
========================================================================================================================
GraalVM Native Image: Generating 'toolkit' (executable)...
========================================================================================================================
[1/7] Initializing...                                                                                    (9.2s @ 0.20GB)
 Version info: 'GraalVM 22.2.0 Java 17 CE'
 Java version info: '17.0.4+8-jvmci-22.2-b06'
 C compiler: cc (null, null, 0.0.0)
 Garbage collector: Serial GC
 1 user-specific feature(s)
 - org.graalvm.home.HomeFinderFeature: Finds GraalVM paths and its version number
[2/7] Performing analysis...  [*********]                                                               (45.3s @ 2.77GB)
  11,123 (90.04%) of 12,354 classes reachable
  18,642 (59.17%) of 31,506 fields reachable
  57,906 (57.83%) of 100,137 methods reachable
     524 classes,   194 fields, and 2,046 methods registered for reflection
      79 classes,   196 fields, and   136 methods registered for JNI access
       5 native libraries: -framework CoreServices, -framework Foundation, dl, pthread, z
[3/7] Building universe...                                                                               (4.7s @ 1.45GB)
[4/7] Parsing methods...      [**]                                                                       (3.6s @ 1.88GB)
[5/7] Inlining methods...     [***]                                                                      (2.2s @ 3.94GB)
[6/7] Compiling methods...    [*****]                                                                   (31.6s @ 4.19GB)
[7/7] Creating image...                                                                                  (5.6s @ 2.77GB)
  25.79MB (49.67%) for code area:    37,581 compilation units
  25.84MB (49.78%) for image heap:  290,531 objects and 175 resources
 292.13KB ( 0.55%) for other data
  51.92MB in total
------------------------------------------------------------------------------------------------------------------------
Top 10 packages in code area:                               Top 10 object types in image heap:
   1.65MB sun.security.ssl                                     5.53MB byte[] for code metadata
1021.89KB java.util                                            2.78MB java.lang.String
 919.87KB picocli                                              2.73MB java.lang.Class
 731.85KB com.sun.crypto.provider                              2.62MB byte[] for general heap data
 565.20KB java.lang.invoke                                     2.42MB byte[] for java.lang.String
 518.23KB java.lang                                            1.46MB byte[] for embedded resources
 504.26KB org.jline.reader.impl                              955.88KB com.oracle.svm.core.hub.DynamicHubCompanion
 476.05KB c.s.org.apache.xerces.internal.impl.xs.traversers  663.69KB byte[] for reflection metadata
 458.58KB sun.security.x509                                  623.30KB java.util.HashMap$Node
 438.98KB com.sun.org.apache.xerces.internal.impl            580.77KB java.lang.String[]
  18.36MB for 389 more packages                                4.51MB for 2478 more object types
------------------------------------------------------------------------------------------------------------------------
                        6.3s (5.7% of total time) in 32 GCs | Peak RSS: 5.93GB | CPU load: 5.50
------------------------------------------------------------------------------------------------------------------------
Produced artifacts:
......

GraalVM带来的惊人效果

启动时间

启动时间代码添加:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {
        long begin = System.currentTimeMillis();
        ......
        try {
            ......
            long end = System.currentTimeMillis();
            long runTime = end - begin;
            System.out.println("startUp cost runTime: " + runTime);
            ......
        } finally {
            ......
        }
    }

使用IDEA启动代码,启动时间如下:

AOT提前编译后native-image启动时间:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
➜  target git:(develop-v0.6.6)./toolkit
......
startUp cost runTime: 11

占用内存的效果

项目代码统计:

编译后可在linux、树莓派、mac系统和windows系统可运行的镜像;

上述的项目配置和落地实践项目见: https://github.com/IoT-Technology/IoT-Toolkit

结束语

GraalVM对于JVM的开发人员来说,无疑是个非常好的消息。但是留给JVM的时间真的不多了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java在云原生的破局利器——AOT(JIT与AOT)
JIT(Just-in-Time,实时编译)一直是Java语言的灵魂特性之一,与之相对的AOT(Ahead-of-Time,预编译)方式,似乎长久以来和Java语言都没有什么太大的关系。但是近年来随着Serverless、云原生等概念和技术的火爆,Java JVM和JIT的性能问题越来越多地被诟病,在Golang、Rust、NodeJS等新一代语言的包夹下,业界也不断出现“云原生时代,Java已死”的言论。那么,Java是否可以使用AOT方式进行编译,摆脱性能的桎梏,又是否能够在云原生时代焕发新的荣光?本文会带着这样的疑问,去探索Java AOT技术的历史和现状。
燃192
2023/02/28
4.4K0
Java在云原生的破局利器——AOT(JIT与AOT)
过两年 JVM 可能就要被 GraalVM 替代了
GraalVM 是 Oracle 大力发展和想要推广的新一代 JVM ,目前很多框架都已经渐渐支持 GraalVM 了,比如我们在用的 Spring 也已经推出了对 GraalVM 兼容的工具包了。
古时的风筝
2022/12/18
12.5K0
过两年 JVM 可能就要被 GraalVM 替代了
Graal VM:云原生时代的Java
文章为笔者原创,首发于:https://icyfenix.cn/tricks/graalvm/
周志明
2020/05/02
2K0
Graal VM:云原生时代的Java
多语言混编的未来-用 GraalVM 实现 Java 与 Python/R 的无缝交互
在云原生、微服务架构盛行的今天,Java 应用面临两大核心挑战:启动速度慢和内存占用高。传统 JVM 的类加载、JIT 预热等机制导致 Spring Boot 应用启动时间长达数秒,而容器化部署对资源敏感的特性进一步放大了这一问题。Oracle 推出的 GraalVM 通过 Native Image(AOT 编译) 和 高性能 JIT 编译器 技术,将 Java 应用的启动时间压缩至毫秒级,内存占用降低 5-10 倍,同时支持多语言互操作,重新定义了 Java 运行时的边界。
一键难忘
2025/09/21
1530
在spring boot3中使用native image
在之前spring boot3文章中我们介绍了,spring boot3的一个重要特性就是支持把spring boot3的应用编译成为GraalVM的Native Image。
程序那些事
2023/01/30
2.8K0
Quarkus经GraalVM native-image编译后启动只需0.07秒(9)
quarkus号称超音速亚原子JAVA为Graalvm量身定制的java堆栈,是否名副其实呢?下面就来看看真实情况如何。动手前先简单介绍下Graalvm,它是oracle出品的一个AOT编译器,可以将应用程序编译成本地映像,通俗的说可以将java编译成机器可直接执行的程序,可以参考go语言的编译输出产物。而且graalvm不仅仅支持java,对其他语言也有很好的支持。下面先看一张quarkus的java应用程序在传统的vm下面和graalvm下面的资源占用图。
kl博主
2023/11/18
7690
Quarkus经GraalVM native-image编译后启动只需0.07秒(9)
深入探索Spring Boot 3与GraalVM Native Image的原生编译原理
在云原生技术快速发展的2025年,Java生态正经历着一场深刻的变革。传统基于JVM的Spring Boot应用虽然功能强大,但在启动速度、内存占用等关键指标上,与Go、Rust等原生语言相比仍存在明显差距。这正是GraalVM Native Image技术引起广泛关注的根本原因——它让Spring应用首次具备了与原生语言同台竞技的能力。
用户6320865
2025/08/27
3700
深入探索Spring Boot 3与GraalVM Native Image的原生编译原理
Spring Native 初体验及对比
| 导语:由于笔者工作项目上的平台产品特性设计原因,用户在平台产品使用过程中会产生数量不少的 Java Spring Boot 微服务,加上 Java 服务本身资源消耗大(尤其内存消耗),造成资源成本很高。因此考虑调研将 Java Spring Boot 服务包编译为本地可运行程序的方式,记录亦供参考。
schema
2022/05/26
7.2K0
Spring Native 初体验及对比
GraalVM-云原生时代的JVM(Java)
GraalVM是 Oracle 开源的一款通用虚拟机产品,官方称之为 Universal GraalVM,是新一代的通用多语言高性能虚拟机。它可以运行多种编程语言,如Java、JavaScript、Python等,并提供了即时编译(JIT)和AOT编译(AOT)的支持。GraalVM还支持在不同语言之间互相调用,以及嵌入到其他应用程序中使用。这使得GraalVM成为一个非常强大和灵活的工具,可以满足不同应用场景的需求。
MCNU云原生
2023/03/17
1.6K0
GraalVM-云原生时代的JVM(Java)
云原生时代的Spring Boot 3.0: GraalVM原生镜像,启动速度提升近30倍
Spring Boot 3.0 五天前(2022年11月24日)发布了,变化很大,基于spring6.0,spring6.0是Spring下一个未来十年的新开端。
后端云
2023/02/10
4K0
云原生时代的Spring Boot 3.0: GraalVM原生镜像,启动速度提升近30倍
通过 GraalVM 将 Java 程序编译成本地机器码!
这是一个在HotSpot虚拟机基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台使用。
Yano_nankai
2020/07/15
4.9K0
通过 GraalVM 将 Java 程序编译成本地机器码!
Java一分钟之-GraalVM:高性能运行时与编译器
GraalVM,作为Oracle实验室的明星项目,是一款革命性的高性能运行时与编译器平台,它不仅支持Java,还兼容JavaScript、Python、Ruby等多种语言。GraalVM通过其独特的即时编译(JIT)和提前编译(AOT)技术,为应用程序带来了显著的性能提升和跨语言互操作性。本文将深入浅出地探讨GraalVM的核心优势、常见问题、易错点及其规避策略,并附带实用代码示例。
Jimaks
2024/06/12
1.8K0
windows下使用graalvm/spring native将JAVA程序构建为本地可执行的exe程序
使用graalvm aot编译器将java程序编译为本地机器码,大幅提升性能。随手建一个空springboot项目玩一下启动速度提升肉眼可见,内存占用也大幅下降
路过君
2022/04/13
2.6K0
windows下使用graalvm/spring native将JAVA程序构建为本地可执行的exe程序
使用GraalVM 构建 Spring Boot 3.0 原生可执行文件
既然是VM,那肯定也是一个虚拟机,那它跟JVM有关系吗?有一定关系,GraalVM 可以完全取代上面提到的那几种虚拟机,比如 HotSpot。把你之前运行在 HotSpot 上的代码直接平移到 GraalVM 上,不用做任何的改变,甚至都感知不到,项目可以完美的运行。但是 GraalVM 还有更广泛的用途,不仅支持 Java 语言,还支持其他语言。这些其他语言不仅包括嫡系的 JVM 系语言,例如 Kotlin、Scala,还包括例如 JavaScript、Nodejs、Ruby、Python 等,如图。
阿提说说
2022/12/19
8.9K1
使用GraalVM 构建 Spring Boot 3.0 原生可执行文件
Java Cloud Native 的未来 Graal AOT 编译器
Java 这门语言与生俱来的显著特性就是“一次编译,到处运行”,这种功能得益于 JVM 平台的支持,Java 程序通常通过将其打包为 JAR 或 WAR 包,并依赖 JVM 和 Servlet 容器来运行。其底层运行时 JVM 采用 JIT(即时编译)模式来执行程序代码,JVM 会在运行时进行编译优化和动态执行代码,这通常会导致较高的内存占用。这样的好处是采用 JIT 可以热更新和热部署程序,并且 JVM 可以在运行期间对程序进行动态分析,来实时优化程序以达到最好的性能状态。
一大块芝士
2024/07/23
4130
Java Cloud Native 的未来 Graal AOT 编译器
借助 Spring Boot 和 GraalVM 实现原生 Java
作者 | Josh Long 译者 | 张卫滨 策划 | 丁晓昀 本文是“Native Compilations Boosts Java”系列文章的一部分。你可以通过 RSS 订阅接收新文章更新通知。 Java 在主导着企业级应用。但是在云中,采用 Java 的成本要比其竞争者更高。使用 GraalVM 进行原生编译降低了在云中 Java 的成本:它所创建的应用启动更快,使用的内存也更少。 原生编译为 Java 用户带来了很多的问题:原生 Java 会如何改变开发方式?我们在什么情况下该转向
深度学习与Python
2023/04/01
1.1K0
借助 Spring Boot 和 GraalVM 实现原生 Java
Spring Native 项目,把 Spring 项目编译成原生程序!
Spring 发布了 Spring Native 的 beta 版本,该功能已经在 start.spring.io 上可用了。
Yano_nankai
2021/03/29
3.4K0
Java 革新之路:GraalVM 原生镜像
Java 主导着企业级应用。但在云计算领域,采用 Java 的成本比它的一些竞争对手更高。原生编译降低了在云端采用 Java 的成本:用它创建的应用程序启动速度更快,使用的内存更少。
xcbeyond
2022/09/07
1.7K0
Java 革新之路:GraalVM 原生镜像
笔记:追随云原生的Java
但在微服务时代是提倡服务围绕业务能力(不同的语言适合不同的业务场景)而非技术来构建应用,不再追求实现上的一致,一个系统由不同语言、不同技术框架所实现的服务来组成是完全合理的。服务化拆分后,很可能单个微服务不再需要再面对数十、数百 GB 乃至 TB 的内存。有了高可用的服务集群,也无须追求单个服务要 7×24 小时不可间断地运行,它们随时可以中断和更新。不仅如此,微服务对镜像体积、内存消耗、启动速度,以及达到最高性能的时间等方面提出了新的要求。这两年的网红概念 Serverless(以及衍生出来的Faas) 也进一步增加这些因素的考虑权重,而这些却正好都是 Java 的弱项:哪怕再小的 Java 程序也要带着厚重的Rumtime(Vm和StandLibrary)——基于 Java 虚拟机的执行机制,使得任何 Java 的程序都会有固定的内存开销与启动时间,而且 Java 生态中广泛采用的依赖注入进一步将启动时间拉长,使得容器的冷启动时间很难缩短。 举两个例子。软件工业中已经出现过不止一起因 Java 这些弱点而导致失败的案例。如 JRuby 编写的 Logstash,原本是同时承担部署在节点上的收集端(Shipper)和专门转换处理的服务端(Master)的职责,后来因为资源占用的原因,被 Elstaic.co 用 Golang 的 Filebeat 代替了 Shipper 部分的职能。又如 Scala 语言编写的边车代理 Linkerd,作为服务网格概念的提出者,却最终被 Envoy 所取代,其主要弱点之一也是由于 Java 虚拟机的资源消耗所带来的劣势。 1.变革之火 1.1 Complie Native Code 显然,如果将字节码直接编译成可以脱离 Java 虚拟机的原生代码则可以解决所有问题。 如果真的能够生成脱离 Java 虚拟机运行的原生程序,将意味着启动时间长的问题能够彻底解决,因为此时已经不存在初始化虚拟机和类加载的过程。也意味着程序马上就能达到最佳的性能,因为此时已经不存在即时编译器运行时编译,所有代码都是在编译期编译和优化好的。同理,厚重的Runtime也不会出现在镜像中。 Java 并非没有尝试走过这条路。从GCJ到 Excelsior JET再到 GraalVM 中的 SubstrateVM 模块再到 2020 年中期建立的 Leyden 项目,都在朝着提前编译(Ahead-of-Time Compilation,AOT)生成原生程序这个目标迈进。Java 支持提前编译最大的困难在于它是一门动态链接的语言,它假设程序的代码空间是开放的(Open World),允许在程序的任何时候通过类加载器去加载新的类,作为程序的一部分运行。要进行提前编译,就必须放弃这部分动态性,假设程序的代码空间是封闭的(Closed World),所有要运行的代码都必须在编译期全部可知。 这一点不仅仅影响到了类加载器的正常运作,除了无法再动态加载外,反射(通过反射可以调用在编译期不可知的方法)、动态代理、字节码生成库(如 CGLib)等一切会运行时产生新代码的功能都不再可用——如果将这些基础能力直接抽离掉,Hello world 还是能跑起来,大部分的生产力工具都跑不起来,整个 Java 生态中绝大多数上层建筑都会轰然崩塌。随便列两个Case:Flink的SQL API会解析SQL并生成执行计划,这个时候会通过JavaCC动态生成类加载到代码空间中去;Spring也有类似的情况,当AOP通过动态代理的方式去生成相关逻辑时,本质还是在Runtime时生成代码并加载进去。 要获得有实用价值的提前编译能力,只有依靠提前编译器、组件类库和开发者三方一起协同才可能办到——可以参考Quarkus。 Quarkus和我们上述的方法如出一辙,以Dependency Inject为例:所有要运行的代码都必须在编译期全部可知,在编译期就推导出来相关的Bean,最后交给 GraalVM来运行。 1.2 Memory Access Efficiency Improvement Java 即时编译器的优化效果拔群,但是由于 Java“一切皆为对象”的前提假设,导致它在处理一系列不同类型的小对象时,内存访问性能很差。这点是 Java 在游戏、图形处理等领域一直难有建树的重要制约因素,也是 Java 建立 Valhalla 项目的目标初衷。 这里举个例子来说明此问题,如果我想描述空间里面若干条线段的集合,在 Java 中定义的代码会是这样的: public record Point(float x, float y, float z) {} public record Line(Point start, Point end) {} Line[] lines; 面向对象的内存布局中,对象标识符(Object Ident
泊浮目
2024/01/09
2030
Java一分钟之-GraalVM Native Image:构建原生可执行文件
在Java开发领域,GraalVM Native Image是一个令人兴奋的技术革新,它允许我们将Java应用程序编译成独立的、原生的可执行文件,从而实现近乎瞬时的启动时间和更低的内存消耗。这一突破性功能对于微服务、桌面应用乃至嵌入式系统具有重要意义。本文旨在深入浅出地探讨GraalVM Native Image的使用,揭示常见的挑战、易错点,并提供实用的解决策略和代码示例。
Jimaks
2024/06/13
1.8K0
推荐阅读
相关推荐
Java在云原生的破局利器——AOT(JIT与AOT)
更多 >
领券
一站式MCP教程库,解锁AI应用新玩法
涵盖代码开发、场景应用、自动测试全流程,助你从零构建专属AI助手
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档