JavaFX打包Jar在部分Linux和MacOS运行失败:Glass工厂类加载错误
问题:JavaFX打包Jar在部分MacOS和Linux系统无法运行
我用IntelliJ打包了一个Jar文件,在Windows和部分MacOS系统能正常运行,但在部分MacOS和Linux系统启动失败。
已尝试操作
- 将JavaFX版本从17降级至11
- 添加了
module-info.java并引入JavaFX Controls与FXML模块
build.gradle 内容
plugins { id 'checkstyle' id 'java' id 'application' id 'com.github.johnrengelman.shadow' version '7.1.2' id 'org.openjfx.javafxplugin' version '0.0.13' } repositories { mavenCentral() } dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.0' String javaFxVersion = '17.0.8' implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'win' implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'mac' implementation group: 'org.openjfx', name: 'javafx-base', version: javaFxVersion, classifier: 'linux' implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'win' implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'mac' implementation group: 'org.openjfx', name: 'javafx-controls', version: javaFxVersion, classifier: 'linux' implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'win' implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'mac' implementation group: 'org.openjfx', name: 'javafx-fxml', version: javaFxVersion, classifier: 'linux' implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'win' implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'mac' implementation group: 'org.openjfx', name: 'javafx-graphics', version: javaFxVersion, classifier: 'linux' } test { useJUnitPlatform() testLogging { events "passed", "skipped", "failed" showExceptions true exceptionFormat "full" showCauses true showStackTraces true showStandardStreams = false } } javafx { version = '17' modules = [ 'javafx.controls', 'javafx.fxml' ] } application { mainClass.set("seedu.Launcher") } shadowJar { archiveBaseName = "duke" archiveClassifier = null dependsOn("distZip", "distTar") } checkstyle { toolVersion = '10.2' } run { standardInput = System.in }
报错信息
2023年9月16日 00:08:25 com.sun.javafx.application.PlatformImpl startup 警告:不支持的JavaFX配置:类从“未命名模块@6712f432”加载 java.lang.ClassNotFoundException: com.sun.glass.ui.gtk.GtkPlatformFactory 在 java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) 在 java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) 在 java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:527) 在 java.base/java.lang.Class.forName0(Native Method) 在 java.base/java.lang.Class.forName(Class.java:315) 在 com.sun.glass.ui.PlatformFactory.getPlatformFactory(PlatformFactory.java:42) 在 com.sun.glass.ui.Application.run(Application.java:146) 在 com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:291) 在 com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:293) 在 com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:163) 在 com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:659) 在 com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:679) 在 com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196) 在 java.base/java.lang.Thread.run(Thread.java:829) 加载Glass工厂类失败 主线程异常 java.lang.NullPointerException 在 com.sun.glass.ui.Application.run(Application.java:146) 在 com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:291) 在 com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:293) 在 com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:163) 在 com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:659) 在 com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:679) 在 com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196) 在 java.base/java.lang.Thread.run(Thread.java:829)
解决方案
核心问题是跨平台打包时未正确包含JavaFX的Native库,加上模块加载配置冲突,导致Linux/MacOS系统无法找到依赖的平台组件。
1. 清理重复依赖,用OpenJFX插件统一管理
你同时手动添加了各平台JavaFX依赖和使用OpenJFX插件,两者冲突导致打包时未正确引入对应平台的Native库。修改build.gradle:
- 删除
dependencies块内所有手动添加的javafx-*依赖,OpenJFX插件会自动根据目标平台引入对应版本的依赖 - 同步
javafx块内的版本号与之前使用的一致(如17.0.8)
修改后相关代码如下:
dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.0' } javafx { version = '17.0.8' modules = [ 'javafx.controls', 'javafx.fxml' ] }
2. 调整ShadowJar配置,打包Native库
JavaFX的GUI功能依赖平台特定的Native库,ShadowJar默认不会自动打包这些资源,需手动配置:
shadowJar { archiveBaseName = "duke" archiveClassifier = null // 将各平台的Native库打包到Jar内的native目录 from(configurations.runtimeClasspath) { include '**/lib/**/*.so' // Linux平台 include '**/lib/**/*.dylib' // MacOS平台 include '**/lib/**/*.dll' // Windows平台 into 'native' } // 配置Manifest,指定模块路径与主类 manifest { attributes( 'Main-Class': 'seedu.Launcher', 'Module-Path': './native' ) } }
3. 修正模块加载配置
报错提示类被加载到未命名模块,需确保module-info.java配置正确:
module seedu { requires javafx.controls; requires javafx.fxml; // 若FXML文件在seedu包下,需开放权限给FXML框架访问 opens seedu to javafx.fxml; exports seedu; }
4. 跨平台打包更可靠方案:用jlink生成独立运行镜像
ShadowJar打包的FatJar在JavaFX跨场景下易出问题,更稳定的方式是用jlink生成包含JRE和所有依赖的独立运行镜像:
在build.gradle中添加jlink配置:
jlink { options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages'] launcher { name = 'duke' } }
执行./gradlew jlink后,build/image目录会生成对应平台的可执行文件,无需依赖系统JRE即可直接运行。
5. Linux系统额外依赖检查
若Linux系统仍报错,需检查是否安装GTK3依赖:
- Ubuntu/Debian:
sudo apt-get install libgtk-3-0 - Fedora/RHEL:
sudo dnf install gtk3
内容的提问来源于stack exchange,提问作者user17719642
相关产品推荐
相关产品推荐

