使用Gradle打包JavaFX应用时模块未找到错误的技术问询
Gradle构建JavaFX分发包出现Module Not Found的解决方案
问题重现
运行Gradle生成的JavaFX分发包时出现错误:
Error occurred during initialization of boot layer java.lang.module.FindException: Module com.example.fxnew not found
开发环境运行正常,但执行gradlew clean build生成的my-name-1.0-SNAPSHOT.zip/tar解压后,运行bin目录下的启动脚本报错。项目配置如下:
build.gradle配置
plugins { id 'java' id 'application' id 'org.openjfx.javafxplugin' version '0.0.11' id 'org.beryx.jlink' version '2.24.1' } group 'com.example' version '1.0-SNAPSHOT' repositories { mavenCentral() } ext { junitVersion = '5.8.2' } tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } application { mainModule = 'com.example.fxnew' mainClass = 'com.example.fxnew.HelloApplication' } javafx { version = '19' modules = ['javafx.controls', 'javafx.fxml'] } dependencies { implementation('org.controlsfx:controlsfx:11.1.1') testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}") } test { useJUnitPlatform() } jlink { imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip") options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'] launcher { name = 'app' } } jlinkZip { group = 'distribution' } java { modularity.inferModulePath.set(true) } distributions { main { distributionBaseName = 'my-name' } }
module-info.java配置
module com.example.fxnew { requires javafx.controls; requires javafx.fxml; requires org.controlsfx.controls; opens com.example.fxnew to javafx.fxml; exports com.example.fxnew; }
问题原因
gradlew build触发的是application插件的distZip/distTar任务,生成的分发包默认使用传统的classpath启动方式,而非模块化应用所需的module-path。虽然配置了mainModule,但application插件的默认启动脚本不会自动添加--module-path参数,导致JVM无法找到你的模块。
你已经引入了专门处理模块化应用的jlink插件,但未执行对应的打包任务。
解决方案
方案1:使用jlink生成模块化运行镜像(推荐)
jlink会打包包含自定义JRE和所有依赖模块的独立镜像,无需额外JDK即可运行,且自动处理模块路径:
- 执行打包命令:
gradlew clean jlinkZip - 在
build/distributions目录下找到对应平台的压缩包(如app-linux-x86_64.zip); - 解压后,运行
bin/app(对应jlink配置中launcher.name = 'app')即可正常启动应用。
方案2:修复application插件的分发包配置
如果坚持使用application插件生成的分发包,需手动配置启动脚本的JVM参数,指定模块路径:
修改application块的配置,添加applicationDefaultJvmArgs:
application { mainModule = 'com.example.fxnew' mainClass = 'com.example.fxnew.HelloApplication' // 添加模块路径参数 applicationDefaultJvmArgs = [ '--module-path', '$APP_HOME/lib', '--module', 'com.example.fxnew/com.example.fxnew.HelloApplication' ] }
重新执行gradlew clean build,解压分发包后运行bin目录下的启动脚本,即可正常加载模块。
注意事项
- jlink要求所有依赖必须是模块化JAR(存在
module-info.class),你使用的ControlsFX 11.1.1符合要求,无需额外处理; - 确保
module-info.java中的模块声明正确,当前配置已满足需求。
内容的提问来源于stack exchange,提问作者A. Cedano
相关产品推荐
相关产品推荐

