⭐ 推荐:社区规则条款 V1.0

如何用 GraalVM 将 Java 应用编译成原生镜像?

GJ
GJ 资深会员 👑黑卡会员
发布于 2026-10-25 10:27 ·4 浏览 ·0 回复
内容摘要

介绍安装 GraalVM、验证 native-image、编译 Hello 示例及用 Maven 插件构建 Java 原生可执行文件的完整流程,并提示 JDK 21 起工具随附、构建需本机 C 工具链。

学完这篇你能得到一个不依赖 JVM、双击就能跑的原生可执行文件:从安装 GraalVM 到用 Maven 插件编译自己的项目,全程可直接照着敲。

第一步:装好 GraalVM,确认 native-image 命令能跑

这一步装好编译器并验证环境,做完后用 native-image --version 能看到版本号就算过了。

Linux/macOS 推荐用 SDKMAN 安装:

sdk install java 21.0.2-graalce
sdk use java 21.0.2-graalce
java -version

也可以直接下压缩包,解压后设置环境变量:

tar -xzf graalvm-jdk-21_linux-x64_bin.tar.gz
export JAVA_HOME=/opt/graalvm-jdk-21.0.2+13.1
export PATH=$JAVA_HOME/bin:$PATH

然后确认工具链:

native-image --version

注意:GraalVM for JDK 21 起 native-image 已随 JDK 一起分发,不用再装;如果你用的是 JDK 17 时代的 GraalVM 22.x,需要额外执行 gu install native-image,否则会提示 command not found。

第二步:先拿一个 Hello 程序试编译

这一步验证整条链路是通的,做完后你会得到一个几十 MB 的可执行文件,启动时间在毫秒级。

新建 Hello.java:

public class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, Native Image");
    }
}

编译并生成原生镜像:

javac Hello.java
native-image Hello
./hello

native-image Hello 默认产出名为 hello 的可执行文件,--no-fallback 参数建议加上,这样缺配置时直接报错,而不是偷偷退化成需要 JVM 的模式,方便你早点发现问题。

注意:构建需要本机 C 工具链。Linux 装 gcc、zlib-devel、glibc-devel;macOS 装 Xcode Command Line Tools(xcode-select --install);Windows 装 Visual Studio 2022 生成工具加 Windows SDK。缺了会在构建中期报 gcc: command not found 之类的错误。

第三步:用 Maven 编译真实项目

这一步把上面的流程搬进自己的工程,做完后 mvn -Pnative package 就能产出原生可执行文件。

在 pom.xml 的 <build><plugins> 里加 GraalVM 官方的 native 插件:

<plugin>
  <groupId>org.graalvm.buildtools</groupId>
  <artifactId>native-maven-plugin</artifactId>
  <version>0.10.3</version>
  <extensions>true</extensions>
  <executions>
    <execution>
      <id>build-native</id>
      <goals><goal>compile-no-fork</goal></goals>
      <phase>package</phase>
    </execution>
  </executions>
</plugin>

然后执行:

mvn -Pnative package

产物在 target/ 下,是当前平台的可执行文件。Gradle 项目加 org.graalvm.buildtools.native 插件后跑 ./gradlew nativeCompile。Spring Boot 3.x 项目只要在 Initializr 建项目时勾选 GraalVM Native Support,直接用 mvn -Pnative native:compile 即可。

注意:构建过程很吃内存,默认可能占用 4~8GB。机器内存小于 8GB 时用 -J-Xmx6g 限制上限,否则容易 OOM 中断。另外 native-image 不支持交叉编译,Linux 上构建的产物只能在 Linux 跑,Windows 产物只能在 Windows 跑。

第四步:补齐反射、资源和动态代理配置

这一步解决「编译能过但运行时报 ClassNotFoundException / 反射拿不到方法」的问题,做完后程序行为才和 JVM 上一致。

GraalVM 在构建期做静态分析,用反射动态加载的类它看不见。最省事的办法是用 agent 跑一遍程序,把配置采集出来:

java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar your-app.jar

正常点一遍功能后停止程序,目录里会生成 reflect-config.json、resource-config.json、proxy-config.json 等文件,打包时会自动读取。手工维护则用 -H:ReflectionConfigurationFiles=reflect-config.json 指定。

注意:agent 只采集你实际走到的代码路径,冷门分支的反射调用采不到。上线前把关键业务路径都点一遍,或者给关键类手工补 reflect-config.json。

第五步:验证产物

这一步确认结果达标。检查三件事:文件大小(简单程序通常 10~30MB,Spring Boot 应用常见 80~150MB)、启动耗时(用 time ./hello 对比 JVM 启动)、功能是否完整。加 -H:+ReportExceptionStackTraces 构建,运行时报错时堆栈更可读。

小结

  • GraalVM for JDK 21 起 native-image 已内置,老版本才需要 gu install
  • 先拿 Hello 程序跑通链路,再上 Maven 插件,排查成本最低
  • 构建依赖本机 C 工具链,且不支持交叉编译
  • 构建吃内存,用 -J-Xmx 控制;加 --no-fallback 让问题早暴露
  • 反射、资源、动态代理必须靠 agent 采集或手工配置
本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2532.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~