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

如何用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

原因分析

  1. 第一个错误:Gradle默认生成的Jar仅包含项目代码,不包含JavaFX依赖。JavaFX不属于JDK默认模块,运行时必须显式指定模块路径或打包依赖。
  2. 第二个错误:命令中使用的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:24:54