首页 > 解决方案 > linux 上的干净部署 - java.lang.ClassNotFoundException: javafx.fxml.FXMLLoader

问题描述

我有一个 Java (JavaFX) 应用程序,它是在笔记本电脑 A 上使用 Gradle 构建的。当我将它部署到笔记本电脑 B 时,它无法运行并抛出以下异常:

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:900)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.NoClassDefFoundError: javafx/fxml/FXMLLoader
    at main.Main.start(Main.java:85)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
    ... 1 more
Caused by: java.lang.ClassNotFoundException: javafx.fxml.FXMLLoader
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    ... 10 more

我使用 gradle 插件构建了一个可执行的 jar。它还构建了一个 zip 和 tar 文件。zip(和 tar)文件包含一个带有运行应用程序脚本的 bin 目录和一个包含大量 jar 文件的 lib 目录。

我有一个以前的问题

Error: JavaFX runtime components are missing, and are required to run this application

我在这里找到了解决方案:

缺少 Maven Shade JavaFX 运行时组件

我创建了一个包装类,其中包含一个调用 main(javafx)的 main(非 javafx)。

我目前的问题:

全新安装 Linux Mint - 19.3 Cinnamon Kernal - 5.3.0-53-generic

gradle-6.0.1

Java 版本 -

openjdk 11.0.7 2020-04-14
OpenJDK Runtime Environment (build 11.0.7+10-post-Ubuntu-2ubuntu218.04)
OpenJDK 64-Bit Server VM (build 11.0.7+10-post-Ubuntu-2ubuntu218.04, mixed mode, sharing)

如果我使用(爆炸的)zip文件中的脚本:

./MyApp/bin/MyApp config.json

或者只是执行应用程序:

java -jar MyApp.jar config.json

这两个都失败了

使用 ZIP 文件内容,我探索了 gradle 部署的 jar 文件。

MyApp.jar
* javafx-graphics-11.jar
* javafx-base-11.jar
javafx-controls-11-linux.jar 
javafx-graphics-11-linux.jar
javafx-base-11-linux.jar
joda-time-2.10.5.jar

'*' 文件是代理,只包含一个清单。'linux' jar 包含 JavaFX 类,但没有文件包含:javafx.fxml.FXMLLoader

我的 - build.gradle

plugins {
  id 'application'
  id 'org.openjfx.javafxplugin' version '0.0.8'
}
javafx {
    version = "11"
    modules = [ 'javafx.controls' ]
}
repositories {
    mavenLocal()
    mavenCentral()
}
sourceCompatibility = '11'

[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

if (!hasProperty('mainClass')) {
    ext.mainClass = 'Main'
}
mainClassName = "Main"
run {
    args 'config.json'
}
dependencies {
    compile "joda-time:joda-time:2.10.5"
    testCompile "junit:junit:4.12"
}
jar {
    manifest {
        attributes 'Main-Class': 'Main'
    }
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

任何人都可以看看我做错了什么。这个应用程序需要在一个干净的系统上运行,除了 Java(最好是 OpenJDK)之外没有任何期望。

我还希望它在 Windows 10 平台上运行,所以任何人都可以告诉我如何让 gradle 构建包含“win”等效 jar 文件:

javafx-controls-11-win.jar 
javafx-graphics-11-win.jar
javafx-base-11-win.jar

亲切的问候

斯图尔特

标签: javalinuxgradlejavafx

解决方案


在 build.gradle 的 javafx 部分中,您需要包含 fxml 模块:

javafx {
    version = "11"
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

请注意,我在 Linux 上的版本“11”javafx 遇到了一些奇怪的问题,因此您可能希望将其更改为 13 或 14。JavaFX 版本至少需要 JDK 11,因此您可以在不更改 JDK 的情况下升级 JavaFX 版本。


推荐阅读