双平台GraalVM编译二进制程序

本文示例均采用Java11,GraalVM目前无法支持跨平台编译,比如,我通过Linux直接编译Windows可执行的exe,是不行的。

Go语言是可以的

因此,需要掌握两种平台的GraalVM的安装、使用。

一、背景

1.1 为何GraalVM快?

常规Java编译的Jar,为了考虑平台的兼容性,在启动后,将字节码解释为机器码,这个过程叫做JIT编译。所以启动上会慢。

GraalVM编译的二进制程序,在编译时直接将字节码转为了机器码,这个过程叫做AOT编译。所以启动上会快,但是对反射支持的就不友好。

因此Java严格来说既是编译型,又是解释型。只不过编译成的是字节码。

截止到2023年05月,总结GraalVM的弱项

  1. 容量占用:使用Graalvm编译后的exe,首先需要依赖C++的开发环境,并且里面还带了JDK编译后的机器码,所以内存约至少10M以上。
  2. 失去原有特性:如Java跨平台的特性、反射、运行时的动态代理等等。
  3. 编译对Java语法有要求,死板且不够灵活,比如上述第二点中的问题。

综上所述,GraalVM只是为了让Java能做而做,而不是为了Java需要做而做。如果以上问题存在,相信以后也不会有太多开发者使用GraalVM开发。不如直接转C/C++/Go,而Go属于最简单的替代品。

1.2 JIT与AOT对比

JIT(Just-in-Time)编译和AOT(Ahead-of-Time)编译是两种不同的编译策略,它们在代码编译和执行的时间点上有所区别。

  1. JIT(Just-in-Time)编译
    • JIT 编译是在程序运行时动态地将字节码或中间代码(如Java字节码)转换为本机机器码。
    • JIT 编译器根据程序的运行时行为和环境进行优化,并将热点代码(频繁执行的代码)即时编译为本机机器码。
    • JIT 编译器可以根据特定硬件平台的特性进行优化,以提高执行速度和性能。
    • JIT 编译通常用于解释性语言或虚拟机中,例如Java虚拟机(JVM)。
  2. AOT(Ahead-of-Time)编译
    • AOT 编译是在程序运行之前将源代码或中间代码(如字节码)静态编译为本机机器码。
    • AOT 编译器在编译阶段进行优化,根据目标平台的特性生成高效的本机代码。
    • AOT 编译可以提供更快的启动时间和更稳定的性能,因为代码已经被编译为本机机器码,无需再进行即时编译。
    • AOT 编译通常用于静态语言或需要更高性能的应用程序,例如C/C++编译器。

主要区别:

  • JIT 编译是在运行时动态地将代码编译为机器码,而 AOT 编译是在程序运行之前将代码静态编译为机器码。
  • JIT 编译可以根据运行时行为进行优化,而 AOT 编译在编译阶段进行优化。
  • JIT 编译需要在程序运行时进行编译,可能导致启动延迟和即时编译的开销,而 AOT 编译可以提供更快的启动时间和更稳定的性能。

需要注意的是,JIT 编译和 AOT 编译并不是互斥的概念,而是两种不同的编译策略。在某些情况下,可以结合使用它们,例如GraalVM提供了同时支持 JIT 编译和 AOT 编译的能力,使得可以根据应用程序的需求选择最适合的编译方式。

二、Linux

2.1 前置环境

环境:Centos7.9、科学上网

yum -y install gcc zlib*

2.2 安装GraalVM-ce-java11

使用 uname 命令:

uname -m

该命令将返回当前系统的机器架构信息。如果返回值是 “x86_64”,则表示系统是 AMD64 架构;如果返回值是 “aarch64”,则表示系统是 AArch64 架构。

curl -L -o graalvm-ce-java11-linux-amd64-21.3.3.1.tar.gz https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.3.1/graalvm-ce-java11-linux-amd64-21.3.3.1.tar.gz && tar -zxvf graalvm-ce-java11-linux-amd64-21.3.3.1.tar.gz && cd graalvm-ce-java11-21.3.3.1/bin && ./gu install native-image && ./gu list

执行如图

三、Windows

3.1 前置环境

windows需要预置的C++环境,这边可以自己下,也可以直接使用Visual Studio下载。我的电脑是win11,而且刚好最近编写dll,因此直接使用Visual Studio2022来安装环境。

打开Visual Studio2022-工具-获取工具和功能

之后,需要将cl.exe的所在目录,配置到环境变量PATH中。

3.2 安装GraalVM-ce-java11

详细配置方式可以参照如下内容,两者任选其一即可

执行命令,进行graalvm-jdk11下载

curl -L -o graalvm-ce-java11-windows-amd64-21.3.3.1.zip https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.3.1/graalvm-ce-java11-windows-amd64-21.3.3.1.zip

然后将jdk进行解压,并配置成环境变量,配置成功后验证结果如图所示。

安装native-image

gu install native-image

使用Visual Studio自带的编译工具,按照第四步进行编译即可。

直接使用cmd编译会报错native-image - fatal error C1034: stdio.h: 不包括路径集

四、编译二进制程序

源码地址

4.1 编译字节码

创建Test.java

import java.text.SimpleDateFormat;
import java.util.Date;
class Test {
    public static void main(String[] args) {
        System.out.println("hello world! now time is "+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }
}

编译Test.java

./javac -encoding utf-8 Test.java
# 执行下面这行代码,会发现输出hello world! now time is 2023-05-16 21:10:09
./java Test
# 编译为二进制程序
./native-image Test

如图即为编译成功

移到没有Java环境的路径,执行二进制程序

mv test /root/test && cd && chmod +x test && ./test

4.2 编译jar包

4.2.1 编译原生jar包

执行命令

mvn clean package
native-image -jar pure-demo.jar

在native-image中,即使主线程结束,其他线程一样执行,程序不会退出

4.2.2 编译springboot jar包

保持原来的代码不变基础上,需要引入spring-native和graalvm打包插件

<dependencies>
    <dependency>
        <groupId>org.springframework.experimental</groupId>
        <artifactId>spring-native</artifactId>
        <version>0.9.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.experimental</groupId>
            <artifactId>spring-aot-maven-plugin</artifactId>
            <version>0.9.2</version>
            <executions>
                <execution>
                    <id>test-generate</id>
                    <goals>
                        <goal>test-generate</goal>
                    </goals>
                </execution>
                <execution>
                    <id>generate</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <classifier>exec</classifier>
            </configuration>
        </plugin>
    </plugins>
</build>

<profiles>
    <profile>
        <id>native-image</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.graalvm.nativeimage</groupId>
                    <artifactId>native-image-maven-plugin</artifactId>
                    <version>21.0.0.2</version>
                    <configuration>
                        <!-- native-image需要执行的应用程序的入口点 -->
                        <mainClass>${start.class}</mainClass>
                        <buildArgs>
                            <buildArg>--enable-https</buildArg>
                        </buildArgs>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>native-image</goal>
                            </goals>
                            <phase>package</phase>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

执行命令,直接打包成镜像

mvn clean package -Pnative-image

放一张原生jar的运行耗时。

GraalVM牛逼!

五、参考致谢

  1. GraalVM Native Image: Hello World - YouTube
  2. 官方文档
  3. Spring Tips: The GraalVM Native Image Builder Feature
  4. 参考第3条的视频:将SpringBoot2.3+jdk8应用编译为二进制
  5. 使用GraalVM将Java编译成本机可执行程序_哔哩哔哩_bilibili
  6. 手把手将你的Java maven项目通过GraalVM打包成windows可执行程序 - Asher的博客
  7. 使用GraalVM将Java编译成本机可执行程序_哔哩哔哩_bilibili
  8. 手把手将你的Java maven项目通过GraalVM打包成windows可执行程序 - Asher的博客
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Ubuntu上安装 GraalVM 中的 `native-image` 工具,可以按照以下步骤操作: 1. 下载 GraalVM:首先,需要下载适用于 Ubuntu 的 GraalVM 发行版。前往 GraalVM 官方网站(https://www.graalvm.org/)选择适合你的 Ubuntu 版本的 GraalVM 版本进行下载。确保选择包含 Native Image 功能的版本。 2. 解压缩 GraalVM:将下载的 GraalVM 压缩包解压到你选择的目录中。可以使用以下命令,将 `<graalvm_version>` 替换为你下载的 GraalVM 版本号,例如 `graalvm-ce-java11-21.3.0`。 ``` tar -xvf <graalvm_version>.tar.gz ``` 3. 设置环境变量:打开终端,并编辑你的 `.bashrc` 或 `.bash_profile` 文件(取决于你使用的是哪个),将以下行添加到文件末尾: ``` export GRAALVM_HOME=/path/to/graalvm_directory export PATH=$GRAALVM_HOME/bin:$PATH ``` 请确保将 `/path/to/graalvm_directory` 替换为你解压缩 GraalVM 的目录路径。保存文件后,执行以下命令使更改生效: ``` source ~/.bashrc ``` 或 ``` source ~/.bash_profile ``` 4. 安装 Native Image:运行以下命令,使用 `gu`(GraalVM 工具)安装 `native-image`。 ``` gu install native-image ``` 这将下载并安装 `native-image` 工具。 5. 验证安装:运行以下命令来验证 `native-image` 是否已成功安装。 ``` native-image --version ``` 如果成功安装,将显示 `native-image` 工具的版本号。 现在,你应该已经成功在 Ubuntu 上安装了 `native-image` 工具,并能够使用它来构建本机映像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值