You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java模块化(JPMS)下JavaFX应用资源加载失败求助

解决JPMS下JavaFX资源加载返回null的问题

我明白你在把JavaFX应用迁移到JPMS时遇到的资源加载困扰——javaClass.getResource("/fxml/scene-splash.fxml")返回null,临时加classpath能解决但不符合模块化规范。咱们一步步来搞定这个问题:

问题根源

你的资源目录src/main/resources被单独放到了模块路径(-p参数)里,这会让它变成一个自动模块(没有module-info.java的模块)。而JPMS中,模块之间的资源访问是受限制的,主模块donim.application默认无法访问自动模块里的资源,这就是返回null的原因。临时加--class-path是把资源丢到非模块化的ALL-UNNAMED模块里,虽然能绕过去,但不是正规的模块化做法。

正确解决方案

1. 确保资源属于主模块的一部分

首先要让src/main/resources下的资源被打包到主模块donim.application中,也就是和module-info.java同目录。对于Gradle Kotlin项目,默认配置应该已经做了这件事,但可以检查build.gradle.kts的sourceSets配置确认:

sourceSets.main {
    kotlin.srcDir("src/main/kotlin")
    resources.srcDir("src/main/resources")
}

这个配置会让Gradle把resources里的文件复制到编译输出目录(比如out/production/classes),这样资源就成为主模块的一部分了。

2. 修正IntelliJ的运行配置

修改你的运行配置,把模块路径(VM参数里的-p)改成只包含out/production/classes,不要单独加out/production/resources。因为资源已经被合并到classes目录里了,单独放会导致资源成为独立的自动模块,引发访问问题。

3. 保持正确的资源加载方式

只要资源属于主模块,你原来的加载代码完全可以正常工作:

javaClass.getResource("/fxml/scene-splash.fxml")

如果想更贴合模块化规范,也可以用模块类加载器加载:

Main::class.java.module.getResourceAsStream("/fxml/scene-splash.fxml")

验证步骤

你可以去out/production/classes目录下看看,是否存在fxml/scene-splash.fxml文件。如果有,说明资源已经正确合并到模块中;如果没有,重新执行Gradle的compileKotlin或者processResources任务,确保资源被复制过去。

额外注意

  • 如果你需要让其他模块访问主模块的资源,需要在module-info.java中用exports声明资源目录,比如:
    exports fxml to javafx.fxml;
    
    不过你这里是自己模块内加载,不需要这个配置。
  • 你已经正确opens了控制器包给javafx.fxml,这部分没问题,FXML可以正常访问控制器类。

内容的提问来源于stack exchange,提问作者Mahozad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 11:02:50