如何用Gradle构建JavaFX应用Jar包并解决运行报错问题
解决Gradle构建JavaFX应用的运行错误
问题详情
用Gradle构建JavaFX应用后,生成的Jar文件运行报错:
C:\Users\user1\IdeaProjects\JavaFXTest\build\libs>java -jar JavaFXTest-1.0-SNAPSHOT.jar Error: Could not find or load main class com.example.javafxtest.HelloApplication Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
确认com.example.javafxtest.HelloApplication类存在且路径正确,当前的build.gradle配置如下:
plugins { id 'java' id 'application' id 'org.javamodularity.moduleplugin' version '1.8.12' id 'org.openjfx.javafxplugin' version '0.0.13' id 'org.beryx.jlink' version '2.25.0' } group 'com.example' version '1.0-SNAPSHOT' repositories { mavenCentral() } jar { manifest { attributes( 'Main-Class': 'com.example.javafxtest.HelloApplication' ) } } ext { junitVersion = '5.9.2' } sourceCompatibility = '17' targetCompatibility = '17' tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } application { mainModule = 'com.example.javafxtest' mainClass = 'com.example.javafxtest.HelloApplication' } javafx { version = '17.0.6' modules = ['javafx.controls', 'javafx.fxml'] } dependencies { 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' }
尝试过用IntelliJ IDEA重新构建并下载依赖,无效;改用指定模块路径的命令运行,出现新错误:
Graphics Device initialization failed for : d3d, sw Error initializing QuantumRenderer: no suitable pipeline found java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found at javafx.graphics@20.0.2/com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:283) at javafx.graphics@20.0.2/com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:253) at javafx.graphics@20.0.2/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:263) at javafx.graphics@20.0.2/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:290) at javafx.graphics@20.0.2/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:162) at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:651) at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409) at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082) Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found at javafx.graphics@20.0.2/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:95) at javafx.graphics@20.0.2/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125) at java.base/java.lang.Thread.run(Thread.java:833) Exception in thread "main" java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082) Caused by: java.lang.RuntimeException: No toolkit found at javafx.graphics@20.0.2/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:275) at javafx.graphics@20.0.2/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:290) at javafx.graphics@20.0.2/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:162) at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:651) at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:409) at javafx.graphics@20.0.2/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363) ... 5 more
原因分析
- 第一个错误:Gradle默认生成的Jar仅包含项目代码,不包含JavaFX依赖。JavaFX不属于JDK默认模块,运行时必须显式指定模块路径或打包依赖。
- 第二个错误:命令中使用的JavaFX SDK版本(20.0.2)与项目配置的JavaFX版本(17.0.6)不匹配,导致图形渲染管线兼容性问题。
解决方案
方案1:用Gradle Application插件直接运行(开发阶段)
无需手动处理依赖,直接执行:
# Windows系统 gradlew.bat run # Linux/macOS系统 ./gradlew run
该插件会自动配置模块路径和依赖,直接启动应用。
方案2:用jlink构建可执行镜像(发布推荐)
你已经在build.gradle中配置了jlink插件,执行以下命令生成包含JRE和所有依赖的独立镜像:
# Windows系统 gradlew.bat jlink # Linux/macOS系统 ./gradlew jlink
生成的镜像位于build/image目录,Windows下运行build/image/bin/app.exe即可启动应用,无需额外配置环境。
方案3:修复手动运行命令
如果必须手动运行Jar,需保证JavaFX SDK版本与项目配置的17.0.6一致,使用以下命令:
java --module-path C:\javafx-sdk-17.0.6\lib --add-modules javafx.controls,javafx.fxml -cp JavaFXTest-1.0-SNAPSHOT.jar com.example.javafxtest.HelloApplication
另外,Windows系统需确保安装了Visual C++ Redistributable,JavaFX图形渲染依赖该组件。
方案4:构建包含依赖的Fat Jar(不推荐)
若要生成包含JavaFX依赖的Jar,可修改build.gradle的jar任务:
jar { manifest { attributes( 'Main-Class': 'com.example.javafxtest.HelloApplication', 'Module-Path': configurations.runtimeClasspath.files.collect { it.name }.join(';') ) } // 打包所有依赖到Jar中 from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } // 排除重复签名文件,避免打包错误 exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA' }
注意:这种方式可能存在模块系统冲突,不如jlink生成的镜像稳定,仅适合临时测试。
内容的提问来源于stack exchange,提问作者Mike Sullivan
相关产品推荐
相关产品推荐

