如何在Gradle7.3+JDK17环境下不使用插件构建可执行Jar文件
问题根因排查
你当前配置存在以下几处核心错误,导致模块无法识别:
- jmod 文件用途错误:jmod 格式仅用于 jlink 构建自定义 JRE 场景,编译、运行阶段的 Java 模块系统无法直接识别 jmod 文件,你需要使用 JavaFX 发布的 jar 格式依赖包。
- 模块路径配置错误:编译阶段未指定 JavaFX 依赖所在路径,运行阶段硬编码了绝对路径且把依赖放到了 resources 目录(resources 是项目资源目录,会被打入最终 Jar,不适合放外部依赖)。
- 模块名不合法:
module-info.java中使用 Java 保留关键字default作为模块名,会直接导致编译失败。
最小无插件配置方案
前置准备
- 去 OpenJFX 官网下载对应平台、对应版本的 JavaFX SDK,解压后把 lib 目录下的所有 jar 包放到项目根目录的
lib/javafx文件夹下;也可以直接通过 Maven 中央库拉取依赖,无需手动下载。 - 修改
module-info.java的模块名,示例:
module com.example.demo { requires javafx.controls; requires javafx.fxml; requires javafx.graphics; requires javafx.base; // 导出主类所在包给JavaFX反射调用 exports com.example.demo to javafx.graphics; }
完整 build.gradle 配置
仅使用 Gradle 内置的 application 插件,无需任何第三方插件:
plugins { id 'application' } repositories { mavenCentral() } // 配置项目全局参数 ext { javafxVersion = "17.0.10" mainModule = "com.example.demo" // 和module-info里的模块名一致 mainClass = "com.example.demo.Main" // 你的主类全限定名 } // 依赖配置,如果用手动下载的jar就用下面的fileTree配置,注释掉maven依赖 dependencies { // 手动引入本地JavaFX依赖的写法 // implementation fileTree(dir: 'lib/javafx', include: ['*.jar']) // 直接从Maven拉取依赖的写法,无需手动下载 implementation "org.openjfx:javafx-base:${javafxVersion}:win" implementation "org.openjfx:javafx-controls:${javafxVersion}:win" implementation "org.openjfx:javafx-graphics:${javafxVersion}:win" implementation "org.openjfx:javafx-fxml:${javafxVersion}:win" // 你的业务依赖 implementation 'org.apache.httpcomponents:httpclient:4.5.13' implementation 'org.apache.httpcomponents:httpcore:4.4.14' implementation 'com.google.code.gson:gson:2.8.9' } mainModule = ext.mainModule mainClass = ext.mainClass // 统一编码配置 compileJava.options.encoding = "UTF-8" compileTestJava.options.encoding = "UTF-8" // 编译阶段模块化配置 compileJava { doFirst { options.compilerArgs += [ '--module-path', classpath.asPath, '--module', mainModule ] } } // 运行阶段配置 run { doFirst { jvmArgs += [ '--module-path', classpath.asPath ] } } // 可执行FatJar配置 jar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE manifest { attributes( 'Main-Class': mainClass, 'Module-Main-Class': mainClass ) } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } }
模块化概念澄清
- Java 9 模块化:JDK 层面的原生模块系统,通过
module-info.java声明模块的名称、依赖、导出包等规则,用来解决类路径冲突、JRE 裁剪等问题,你写的module-info.java就是给这套系统读取的配置。 - Gradle 模块化:指 Gradle 的多项目构建能力,把一个大型项目拆分为多个独立的 Gradle 子项目,每个子项目可以是一个 Java 9 模块,也可以是传统的非模块化项目,和 JDK 模块化是两个不同层面的概念。
- IntelliJ IDEA 模块化:IDEA 项目层面的内容划分规则,一个 IDEA 项目可以包含多个 IDEA 模块,每个模块通常对应一个 Gradle 子项目,IDEA 会自动同步 Gradle 配置,不需要手动修改 IDEA 层面的模块设置。
验证步骤
- 执行
./gradlew compileJava确认编译无报错 - 执行
./gradlew run确认应用可以正常启动 - 执行
./gradlew jar生成可执行 Jar,生成的 Jar 在build/libs目录下,直接执行java -jar 生成的jar名称.jar即可运行。
内容的提问来源于stack exchange,提问作者Santa Monica
相关产品推荐
相关产品推荐

