
本文详解 jpackage 打包时识别 ControlsFX 模块失败的根本原因:ControlsFX 的模块名为 org.controlsfx.controls 而非 controlsfx,需通过 jar --describe-module 确认真实模块名,并在 --add-modules 和 --module-path 中正确引用 JAR 文件路径。
本文详解 jpackage 打包时识别 controlsfx 模块失败的根本原因:controlsfx 的模块名为 `org.controlsfx.controls` 而非 `controlsfx`,需通过 `jar --describe-module` 确认真实模块名,并在 `--add-modules` 和 `--module-path` 中正确引用 jar 文件路径。
在使用 jpackage 构建 JavaFX 应用的原生安装包时,若引入第三方模块(如 ControlsFX),常见错误是误用模块名称或错误配置模块路径,导致 java.lang.module.FindException: Module controlsfx not found。根本问题在于:controlsfx-11.1.2.jar 并不导出名为 controlsfx 的模块,其真实模块名为 org.controlsfx.controls。
✅ 正确步骤:验证并声明 ControlsFX 模块
首先,确认 JAR 的模块声明:
jar --file=controlsfx-11.1.2.jar --describe-module
输出示例:
org.controlsfx.controls@11.1.2 jar:file:///path/to/controlsfx-11.1.2.jar!/module-info.class exports org.controlsfx.control exports org.controlsfx.control.action ... requires java.base mandated requires javafx.controls
→ 可见模块名为 org.controlsfx.controls,而非 controlsfx。
✅ 修正 jpackage 命令
将原命令中错误的 --add-modules javafx.controls,controlsfx 改为:
--add-modules javafx.controls,org.controlsfx.controls
同时,--module-path 必须分别指定 JavaFX jmod 路径和 ControlsFX JAR 路径(注意:JAR 文件本身即可作为模块路径项,无需解压):
jpackage \ --input C:\...\target \ --add-modules javafx.controls,org.controlsfx.controls \ --module-path "C:\...\openjfx-20.0.1_windows-x64_bin-jmods\javafx-jmods-20.0.1" \ --module-path "C:\...\lib\controlsfx-11.1.2.jar" \ --win-console \ --dest C:\outputs \ --main-jar tests-1.0-SNAPSHOT.jar \ --main-class tests.App
⚠️ 注意事项:
- --module-path 可多次使用(如上),但不可合并为单个参数(--module-path a;b 在 Windows 下不被 jlink 正确解析);
- ControlsFX JAR 必须是 模块化 JAR(含 module-info.class),11.1.2 版本满足此要求;
- 若使用非模块化 JAR(自动模块),--describe-module 会显示 No module descriptor found. Derived automatic module.,此时应改用 classpath 方式(见下文备选方案)。
✅ 备选方案:以 classpath 方式引入(适用于自动模块或调试)
若模块路径配置复杂,可将 ControlsFX JAR 放入 --input 目录下的子目录(如 lib/),jpackage 会自动将其加入 classpath:
# 假设 target/ 结构如下: # └── target/ # ├── tests-1.0-SNAPSHOT.jar # └── lib/ # └── controlsfx-11.1.2.jar
此时命令中移除 --add-modules org.controlsfx.controls 和对应 --module-path,仅保留 JavaFX 模块路径:
jpackage \ --input C:\...\target \ --add-modules javafx.controls \ --module-path "C:\...\javafx-jmods-20.0.1" \ --win-console \ --dest C:\outputs \ --main-jar tests-1.0-SNAPSHOT.jar \ --main-class tests.App
生成的 {app}.cfg 文件中将包含:
app.classpath=$APPDIR\lib\controlsfx-11.1.2.jar
该方式不依赖模块系统,兼容性更强,但无法享受 jlink 的精简运行时优势。
✅ 验证打包结果
安装生成的程序后,进入安装目录下的 runtime\bin,执行:
java --list-modules | findstr "controls"
应看到:
javafx.controls@20.0.1 org.controlsfx.controls@11.1.2
表明 ControlsFX 已成功集成进运行时镜像。
总结:jpackage 对模块名称极其敏感,切勿凭直觉命名;始终用 jar --describe-module 查证模块名;模块路径中 JAR 文件与 jmod 目录地位等同,均可直接作为 --module-path 参数;合理选择模块化集成(推荐)或 classpath 集成,兼顾可维护性与运行时效率。

















