辽源市网站建设_网站建设公司_Sketch_seo优化
2025/12/31 19:28:08 网站建设 项目流程

JavaFX Java 模块化 jpackage 打包 exe (手动 jlink 实战 + Gradle插件)


方案一:Java 运行时 + exe 启动器

该方案的通用性很好,但是有一个缺点是生成的包很大,因为它整个JDK环境放进包里了,比如 jdk21 解压后的大小就是300M,再加上项目文件和各种依赖,就会更大。
实现步骤,以 jpakage 为例:

步骤1:打包成 Fat Jar

首先把项目打包成一个可运行Fat Jar,在这jar中包含了所有依赖和启动入口类
Spring Boot Maven 插件可以参考:Spring Boot Maven Plugin
我这里使用的是Gradle 的 shadow 插件,配置如下

plugins{id("java")id("com.gradleup.shadow")version"9.2.2"}

执行插件

.\gradlew clean shadowJar

结果将生成文件:build\libs\summary-1.3-all.jar
文件大小为 28.4 MB
执行命令java -jar summary-1.0-all.jar可直接运行 jar 包,如图

步骤2:打包成 app-image

jpackage `--typeapp-image `--name App `--input.\build\libs\ `--main-jar summary-1.3-all.jar `--icon src/main/resources/excel.ico `--dest.\build\

打包镜像成功后, App 镜像中包括了Java21的运行时 runtime,和可执行程序 App.exe。大小总共有 225 MB,如图

步骤3:打包为安装程序

需要先安装wix314.exe,然后再执行步骤2的命令,去掉其中参数 --type app-image, 采用默认方式即可

jpackage-n App `--input.\build\libs\ `--main-jar summary-1.3-all.jar `--icon src/main/resources/excel.ico `--dest.\build\

安装包的文件大小为: 100M

方案二:模块化构建 Java 运行时

基础知识:
  • module-info.java 文件中, 依赖声明: require, 权限声明: export , open
  • 3个重要工具: jdeps , jlink , jpackage
  • 启动非模块化 java 应用:java -cp "依赖jar路径" com.taj.summary.Launcher
  • 启动模块化 java 应用:java -cp "非模块化jar路径" -p "模块化jar路径" -m 模块名/主函数所在的类名
  • -cp 路径的jar转为未命名模块, 如果把 非模块化jar放入 -p 路径下, 将转为自动模块
  • 未命名模块的依赖权限处理: export 所有包, require 所有模块
  • 自动模块的依赖权限处理: export 所有包, require 所有命名模块, 并且允许访问未命名模块
  • 需要被反射访问的包, 必须开启 open, 也可以在启动命令中对任意模块开启 open

1. 拷贝依赖

build.gradle.kts 配置

// 新增任务: copyDepstasks.register<Copy>("copyDeps"){// 复制运行时依赖到deps目录from(configurations.runtimeClasspath)into(layout.buildDirectory.dir("deps"))}// build 时执行任务 copyDepstasks.named("build"){dependsOn("copyDeps")}

也可以手动执任务 copyDeps

.\gradlew copyDeps

2. 使用 jdeps 分析依赖

输出 依赖模块
# 输出依赖模块: print-module-depsjdeps `--multi-release 21 `--ignore-missing-deps `--print-module-deps `--module-path".\build\deps\;$env:JAVAFX_HOME\jmods"`.\build\libs\summary-1.3.jar# 运行结果:java.base,javafx.controls,javafx.fxml,org.apache.commons.io,org.apache.logging.log4j,org.apache.poi.ooxml,org.kordamp.bootstrapfx.core

如果.\build\deps\中存在非模块化jar, jdeps 无法分析其依赖, 并自动忽略, 所以运行结果 一定是少于或等于实际依赖的

输出 依赖详情
# 输出依赖详情: -v (具体到每个类)jdeps-v `--multi-release 21 `--ignore-missing-deps `--module-path".\build\deps\;$env:JAVAFX_HOME\jmods"`.\build\libs\summary-1.3.jar
结论

根据分析, 得出对 java 和 javafx 的依赖只有3个模块:
java.base,javafx.controls,javafx.fxml
其他第3方依赖, 我们可以不用构建到 java 运行时

3. 使用 jlink 构建 Java 运行时

方法1: 根据 jdeps 的分析结果, 构建 java 运行时

该方法一般用于非模块化项目, 模块化项目也能用(精准控制添加模块)

# 运行时只包括 java 和 javafx 的模块jlink `--module-path"$env:JAVAFX_HOME\jmods"`--add-modulesjava.base,javafx.controls,javafx.fxml `--output.\build\custom-jre
方法2: 从自己的项目模块, 构建 java 运行时

前提条件: 你的项目已经是模块化, 并且所有依赖也都模块化
如果存在非模块化依赖, 需要手动处理, 后面有提供处理脚本
当然, 该方法可以不用进行 jdeps 依赖分析

# add-modules 只添加自己的项目模块, jlink 会自动分析依赖jlink `--module-path".\build\deps\;$env:JAVAFX_HOME\jmods"`--add-modulescom.taj.summary `--output.\build\custom-jre
进一步压缩
jlink `--module-path"$env:JAVAFX_HOME\jmods"`--add-modulesjava.base,javafx.controls,javafx.fxml `--output.\build\custom-jre `--compress=zip-6 `# 启用 ZIP 压缩--strip-debug `# 移除调试信息--no-header-files `# 不包含 native 头文件--no-man-pages# 不包含 man 手册
构建结果

我使用的是微软 JDK 21, 构建出的自定义运行时有 55.7 MB

PSD:\projiects\summary> java-version openjdk version"21.0.9"2025-10-21 LTS OpenJDK Runtime Environment Microsoft-12574459(build 21.0.9+10-LTS)OpenJDK 64-Bit Server VM Microsoft-12574459(build 21.0.9+10-LTS,mixed mode,sharing)

4. 打包: 非模块化项目

# 1 清理, 打包 jar, 复制依赖到 deps.\gradlew clean jar copyDepscp.\build\libs\summary-1.3.jar.\build\deps\# 2 构建运行时 custom-jrejlink `--module-path"$env:JAVAFX_HOME\jmods"`--add-modulesjava.base,javafx.controls,javafx.fxml `--output.\build\custom-jre `--compress=zip-6 `--strip-debug `--no-header-files `--no-man-pages# 3 删除 javafx 依赖, 因为运行时 custom-jre 中已经包含rm.\build\deps\javafx*# 4 打包: 非模块化项目jpackage `--typeapp-image `--name MyApp `--runtime-image

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询