使用Maven Shade打包JavaFX时遭遇FXML加载LoadException问题
JavaFX Shade打包后FXML加载失败:Location is required问题排查
问题场景
按相关帖子配置JavaFX项目,执行mvn clean package打包后,运行java -jar .\target\app-name-1.0.0-ALPHA.jar抛出异常:
Exception in Application start method Exception in thread "main" java.lang.RuntimeException: Exception in Application start method at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901) at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196) at java.base/java.lang.Thread.run(Thread.java:1589) Caused by: javafx.fxml.LoadException: file:/C:/Users/user/Documents/app-name/target/app-name-1.0.0-ALPHA.jar!/view/rename.fxml:14 ... Caused by: java.lang.NullPointerException: Location is required.
FXML加载代码:
final Parent root = FXMLLoader.load(getClass().getResource("/view/rename.fxml"));
项目结构
输入目录:
src/main/java/app-name/AppLauncher.java (不继承Application的启动类) src/main/java/app-name/AppMain.java (继承Application的主类) src/main/resources/view/rename.fxml
编译输出目录:
target/classes/app-name/AppLauncher.class target/classes/app-name/AppMain.class target/classes/view/rename.fxml target/classes/style/style.css target/app-name-1.0.0-ALPHA.jar
pom.xml配置
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <javafx.version>19</javafx.version> </properties> <dependencies> <dependency> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> </dependency> <!-- JavaFX --> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-controls</artifactId> <version>${javafx.version}</version> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-fxml</artifactId> <version>${javafx.version}</version> </dependency> <!-- JavaFX: cross-platform fat jar --> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-graphics</artifactId> <version>${javafx.version}</version> <classifier>win</classifier> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-graphics</artifactId> <version>${javafx.version}</version> <classifier>linux</classifier> </dependency> <dependency> <groupId>org.openjfx</groupId> <artifactId>javafx-graphics</artifactId> <version>${javafx.version}</version> <classifier>mac</classifier> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.10.1</version> <configuration> <release>19</release> </configuration> </plugin> <!-- For fat jar --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>uk.co.conoregan.showrenamer.ShowRenamerLauncher</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build>
打包警告
打包时出现资源重叠警告,暂不认为是直接诱因:
checker-qual-3.5.0.jar, commons-codec-1.10.jar, commons-collections4-4.2.jar, commons-dbcp-1.4.jar, commons-io-2.6.jar, commons-lang3-3.3.2.jar, commons-pool-1.6.jar, jdependency-2.8.0.jar, jdom2-2.0.6.1.jar define 1 overlapping resource: - META-INF/LICENSE.txt javafx-graphics-19-linux.jar, javafx-graphics-19-mac.jar define 320 overlapping classes and resources: - com.sun.prism.es2.BufferFactory - com.sun.prism.es2.ES2Context - com.sun.prism.es2.ES2Context$1 - com.sun.prism.es2.ES2Graphics - com.sun.prism.es2.ES2Light - com.sun.prism.es2.ES2Mesh - com.sun.prism.es2.ES2Mesh$ES2MeshDisposerRecord - com.sun.prism.es2.ES2MeshView - com.sun.prism.es2.ES2MeshView$ES2MeshViewDisposerRecord - com.sun.prism.es2.ES2PhongMaterial - 310 more... commons-codec-1.10.jar, commons-collections4-4.2.jar, commons-dbcp-1.4.jar, commons-io-2.6.jar, commons-lang3-3.3.2.jar, commons-pool-1.6.jar, jdependency-2.8.0.jar define 1 overlapping resource: - META-INF/NOTICE.txt javafx-graphics-19-linux.jar, javafx-graphics-19-mac.jar, javafx-graphics-19-win.jar define 2828 overlapping classes and resources: - META-INF/substrate/config/jniconfig-aarch64-android.json - META-INF/substrate/config/jniconfig-aarch64-darwin.json - META-INF/substrate/config/jniconfig-aarch64-linux.json - META-INF/substrate/config/jniconfig-arm64-ios.json - META-INF/substrate/config/jniconfig-x86_64-darwin.json - META-INF/substrate/config/jniconfig-x86_64-ios.json - META-INF/substrate/config/jniconfig-x86_64-linux.json - META-INF/substrate/config/jniconfig-x86_64-windows.json - META-INF/substrate/config/jniconfig.json - META-INF/substrate/config/reflectionconfig-aarch64-darwin.json - 2818 more... commons-logging-1.1.1.jar, jcl-over-slf4j-1.7.7.jar define 6 overlapping classes: - org.apache.commons.logging.Log - org.apache.commons.logging.LogConfigurationException - org.apache.commons.logging.LogFactory - org.apache.commons.logging.impl.NoOpLog - org.apache.commons.logging.impl.SimpleLog - org.apache.commons.logging.impl.SimpleLog$1 javafx-base-19-win.jar, javafx-controls-19-win.jar, javafx-fxml-19-win.jar, javafx-graphics-19-linux.jar, javafx-graphics-19-mac.jar, javafx-graphics-19-win.jar define 1 overlapping resource: - META-INF/substrate/config/reflectionconfig.json maven-shade-plugin has detected that some class files are present in two or more JARs. When this happens, only one single version of the class is copied to the uber jar. Usually this is not harmful and you can skip these warnings, otherwise try to manually exclude artifacts based on mvn dependency:tree -Ddetail=true and the above output. See https://maven.apache.org/plugins/maven-shade-plugin/
解决方案
1. 修复Shade插件资源处理逻辑
Maven Shade插件默认不会正确合并FXML、CSS这类非Java资源,需要添加专用转换器确保资源被打包到Jar中。修改pom.xml的shade插件配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>uk.co.conoregan.showrenamer.ShowRenamerLauncher</mainClass> </transformer> <!-- 确保FXML、配置文件等资源正确合并 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ResourceBundleAppendingTransformer"/> <transformer implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer"/> <!-- 处理ServiceLoader配置文件,避免JavaFX服务加载失败 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <!-- 可选:排除重复的LICENSE/NOTICE文件,减少打包警告 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/LICENSE.txt</exclude> <exclude>META-INF/NOTICE.txt</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin>
2. 验证资源打包情况
打包后执行jar tf target/app-name-1.0.0-ALPHA.jar,查看Jar内目录结构,确认view/rename.fxml是否存在。如果不存在,检查maven-resources-plugin是否正常工作(默认会自动复制resources目录资源,若有自定义配置需核对)。
3. 调整FXML加载方式(备选)
如果插件配置仍未解决问题,尝试用类加载器加载资源,确保路径匹配:
URL fxmlUrl = getClass().getClassLoader().getResource("view/rename.fxml"); if (fxmlUrl == null) { throw new IllegalStateException("未找到FXML文件: view/rename.fxml"); } final Parent root = FXMLLoader.load(fxmlUrl);
注意这里路径不需要开头的/,类加载器的getResource是从classpath根目录开始查找。
4. 处理JavaFX跨平台依赖冲突
打包警告中的多平台graphics依赖重叠,虽不直接导致FXML加载失败,但可能引发其他运行时问题。可以针对不同平台单独打包,或保留现有配置忽略警告(单一跨平台Jar场景下可接受)。
内容的提问来源于stack exchange,提问作者Conor Egan
相关产品推荐
相关产品推荐

