手把手将你的 Java maven 项目通过 GraalVM 打包成 windows 可执行程序

本贴最后更新于 404 天前,其中的信息可能已经东海扬尘

原文发布于:手把手将你的 Java maven 项目通过 GraalVM 打包成 windows 可执行程序,欢迎使用 RSS 订阅获取最新更新。

1. 背景相关

作为一个程序员,总是会在工作的时候开发一些方便自己工作的程序,但是作为一个 Java 程序员,给自己或者朋友开发的办公小程序总是使用一个 Jar 包并不是一个很好的体验,主要是:

  • 启动不方便
  • 需要 Java 环境
  • 有时候打出来的 Jar 比较大,不便于分享传输

但是现在有了 GraalVM,让这些都不是问题了,直接生成可执行程序,丢哪哪就能用

2. GraalVM

GraalVM 是一款高性能的虚拟机,它能够直接将 Java 程序编译成本地可执行文件,可以在不安装 JVM 的情况下运行程序。当然了它的特性远不止这些,比如支持多语言,更低的内存占用等等,但这些并不是这篇博客所涉及的,有兴趣可以去他们的官网里了解一下。

安装 GraalVM JDK

下载界面:https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.3.1

这里用到的是 Java 17 版本:

下载完成之后,放入你本地的 JDK 目录,例如:

接着配置环境变量

简单的通过 cmd 测试一下

安装 native-image

Native Image 是一种将 Java 代码提前编译为独立可执行文件的技术,此刻执行文件包括应用程序类、依赖、运行时库以及 JDK 静态连接的本机代码。 Graalvm 通过子模块 SubstrateVM 来支持 Native Image,相比 JVM 其生成的程序具有更快的启动时间和更低的运行时开销。

需要在管理员模式下打开一个 cmd 窗口,然后执行:

gu install native-image

3.安装 Visual studio

为了打包成 exe 可执行程序,这一步也是不可避免需要做的,这里推荐安装 2019 版本之后的,我安装的是 visual studio 2022,下载地址:https://visualstudio.microsoft.com/zh-hans/vs/

安装完成以后我们还需要一些配置,不然直接进行打包会失败

配置 cl.exe 到系统的环境变量

安装完 Visual studio 后,你可以通过我的路径匹配找到你的 cl.exe 的路径,并配置 cl.exe 到系统的环境变量**。**

C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.34.31933\bin\Hostx64\x64

如果有问题:可以参考我之前踩过的坑:

【已解决】Default native-compiler executable 'cl.exe' not found via environment variable PATH

4. 将一个简单的 Java 应用打包成可执行程序

这里以一个简单的 Java 应用举例,它的功能是将剪切板上的一大串的 xml 文本解析为排序后的 xml,然后重新放回 xml,方便我们平时在工作的时候对 xml 进行对比。

代码已经放在 github,有需要的可以自取:https://github.com/MingGH/clip-sort-xml

这里贴一下主要代码部分,你可能不信,但它是 ChatGPT 写出来的,我只做了获取剪切板内容和放入剪切板这两个方法。。

添加 graal-sdk 依赖

<dependency>
    <groupId>org.graalvm.sdk</groupId>
    <artifactId>graal-sdk</artifactId>
    <version>21.3.0</version>
    <scope>provided</scope>
</dependency>

对 maven 项目使用跟踪代理生成反射配置

有了代码之后,我们需要对 maven 项目使用跟踪代理生成反射配置

需要先把你的代码打成 jar 包,虽然这里并不是 SpringBoot 项目,但是我使用的是 spring-boot-maven-plugin 对项目进行打包。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>3.0.4</version>
</plugin>

可以通过 IDEA 快速打包,或者通过命令 mvn clean package 进行打包

构建成功之后,我们进入 target 目录下:cd target

然后使用跟踪代理运行应用程序:

执行此命令前注意你的 idea 配置的 JDK 也需要是 GraalVM JDK

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

执行时,会真实的启动你的项目并且执行,所以最好正常流程和异常流程都要测试到。

执行完成之后,会在 target 目录下生成一个 META-INF 的文件夹,这个文件夹中包含的内容就是使用跟踪代理生成的反射配置。

把这个文件夹的内容复制到项目 resources 目录下

然后回到 pom.xml 文件,注释掉 spring-boot-maven-plugin 添加 native-image-maven-plugin ,如下:

<plugin>
    <groupId>org.graalvm.nativeimage</groupId>
    <artifactId>native-image-maven-plugin</artifactId>
    <version>21.2.0</version>
    <executions>
        <execution>
            <goals>
                <goal>native-image</goal>
            </goals>
            <phase>package</phase>
        </execution>
    </executions>
    <configuration>
        <skip>false</skip>
        <imageName>graalvmMaven</imageName>
        <mainClass>run.runnable.clipsortxml.ClipSortXmlApplication</mainClass>
        <buildArgs>
            --no-fallback
        </buildArgs>
    </configuration>
</plugin>

通过 Native Tools Command Prompt 进行打包

现在接近尾声了,从你的 windows 搜索窗口,打开 Native Tools Command Prompt ,然后进入到你的项目路径。

这个控制台我在执行的时候有点奇怪,只能在 C 盘执行,所以我把整个项目复制到了 C 盘的临时目录。

进入对应目录,然后执行:mvn clean package 你就会听到你的电脑起飞了,至少我的电脑是风扇狂转准备起飞了。

当出现 build Success 的时候就表示打包成可执行程序已经完成。

当中可能会碰到一些错误,我已经替你踩过一次坑了,所以可以直接参考我的解决办法:

【已解决】native-image - fatal error C1034: stdio.h: 不包括路径集

【已解决】native-image 抛错 fatal error 1083

【已解决】Default native-compiler executable 'cl.exe' not found via environment variable PATH

完成上面的步骤之后,你会看到在 target 目录,哇,真的有一个.exe 文件,迫不及待去点开试试你的功能。

但是把,如果你是直接使用的我的这个项目,那么快乐还没有来的这么快。

双击之后你会发现一个黑色窗口飘过,然后啥也没发生,其实是因为代码执行出错了

解决 Default flavor mapping not found 错误

我们先按照正常方式进行排查,任意 cmd 窗口执行刚刚打包的那个.exe 文件,就可以看到具体的错误信息:

这个错误也已经解决:

【已解决】native-image:Default flavor mapping not found

这里再重复一下:

这是 agentlib native-image-agent.exe
的 bug,已经有人反馈在 GraalVM 的 issues 中,你可以在这个链接中发现其他人也碰到了这个问题:https://github.com/oracle/graal/issues/5369

解决办法也很简单,在你通过跟踪代理
生成的 META-INF/native-image/resource-config.json 中的 includes
添加一行:{ "pattern":"\\Qsun/datatransfer/resources/flavormap.properties\\E" }

保存然后重新执行 mvn clean package

这时打包出来的 .exe 文件才是真正可用的,这样一来一个 exe 文件,更方便丢给不懂代码的朋友了。

5.参考内容

[native-image] Swing application cannot be compiled on Windows

[native-image] makeShimDLL for java.dll is missing exports and fails

[native-image] java.home property not set

swing JTextField ctrl+v Throw Exception: java.lang.InternalError: Default flavor mapping not found

GraalVM Native Image 快速入门

【已解决】native-image - fatal error C1034: stdio.h: 不包括路径集

GraalVM 与 Spring Native 初体验,一个让你的应用在 100ms 内启动的神器

【已解决】native-image:Default flavor mapping not found

【已解决】native-image 抛错 fatal error 1083

【已解决】Default native-compiler executable 'cl.exe' not found via environment variable PATH

【已解决】native-image:Default flavor mapping not found

【已解决】Could not find agent library native-image-agent on the library path

ChatGPT

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3167 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...