运行 JavaFx 媒体应用程序时出现模块错误

Posted

技术标签:

【中文标题】运行 JavaFx 媒体应用程序时出现模块错误【英文标题】:Module error when running JavaFx media application 【发布时间】:2019-04-13 16:56:12 【问题描述】:

当我使用以下命令运行 JavaFX 11 应用程序时:

/usr/lib/jvm/java-11-openjdk-amd64/bin/java 
-p ~/.m2/repository/org/openjfx/javafx-swing/11/javafx-swing-11.jar:
~/.m2/repository/org/openjfx/javafx-swing/11/javafx-swing-11-linux.jar:
~/.m2/repository/org/openjfx/javafx-graphics/11/javafx-graphics-11.jar:
~/.m2/repository/org/openjfx/javafx-graphics/11/javafx-graphics-11-linux.jar:
~/.m2/repository/org/openjfx/javafx-base/11/javafx-base-11.jar:
~/.m2/repository/org/openjfx/javafx-base/11/javafx-base-11-linux.jar:
~/.m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11.jar:
~/.m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-linux.jar:
~/.m2/repository/org/openjfx/javafx-media/11/javafx-media-11.jar:
~/.m2/repository/org/openjfx/javafx-media/11/javafx-media-11-linux.jar 
--add-modules javafx.controls,javafx.graphics
-classpath ~/development/intellij/OpenPatrician/OpenPatricianStandalone/target/classes:
~/.OpenPatrician/plugins/maps/MinimalMap-Plugin.jar:
~/development/intellij/OpenPatrician/OpenPatricianDisplay/target/classes:
~/.m2/repository/ch/sahits/sahitsUtil/1.2.4/sahitsUtil-1.2.4.jar:
~/.m2/repository/junit/junit/4.12/junit-4.12.jar:
~/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:
~/.m2/repository/org/springframework/boot/spring-boot-starter-log4j2/2.1.0.RELEASE/spring-boot-starter-log4j2-2.1.0.RELEASE.jar:
~/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.11.1/log4j-slf4j-impl-2.11.1.jar:
~/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar:
~/.m2/repository/org/apache/logging/log4j/log4j-api/2.11.1/log4j-api-2.11.1.jar:
~/.m2/repository/org/apache/logging/log4j/log4j-core/2.11.1/log4j-core-2.11.1.jar:
~/.m2/repository/org/apache/logging/log4j/log4j-jul/2.11.1/log4j-jul-2.11.1.jar:
~/.m2/repository/org/slf4j/jul-to-slf4j/1.7.25/jul-to-slf4j-1.7.25.jar:
~/.m2/repository/commons-cli/commons-cli/1.4/commons-cli-1.4.jar:
~/development/intellij/OpenPatrician/OpenPatricianImage/target/classes:
~/development/intellij/OpenPatrician/OpenPatricianModel/target/classes:
~/development/intellij/OpenPatrician/GameEvent/target/classes:
~/.m2/repository/org/glassfish/jaxb/jaxb-runtime/2.3.1/jaxb-runtime-2.3.1.jar:
~/.m2/repository/org/glassfish/jaxb/txw2/2.3.1/txw2-2.3.1.jar:
~/.m2/repository/com/sun/istack/istack-commons-runtime/3.0.7/istack-commons-runtime-3.0.7.jar:
~/.m2/repository/org/jvnet/staxex/stax-ex/1.8/stax-ex-1.8.jar:
~/.m2/repository/com/sun/xml/fastinfoset/FastInfoset/1.2.15/FastInfoset-1.2.15.jar:
~/.m2/repository/javax/activation/javax.activation-api/1.2.0/javax.activation-api-1.2.0.jar:
~/.m2/repository/org/openjfx/javafx-swing/11/javafx-swing-11.jar:
~/.m2/repository/org/openjfx/javafx-swing/11/javafx-swing-11-linux.jar:
~/.m2/repository/org/openjfx/javafx-graphics/11/javafx-graphics-11.jar:
~/.m2/repository/org/openjfx/javafx-graphics/11/javafx-graphics-11-linux.jar:
~/.m2/repository/org/openjfx/javafx-base/11/javafx-base-11.jar:
~/.m2/repository/org/openjfx/javafx-base/11/javafx-base-11-linux.jar:
~/development/intellij/OpenPatrician/OpenPatricianSound/target/classes:
~/development/intellij/OpenPatrician/OpenPatricianUtilities/target/classes:
~/.m2/repository/org/springframework/spring-beans/5.1.2.RELEASE/spring-beans-5.1.2.RELEASE.jar:
~/.m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11.jar:
~/.m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-linux.jar:
~/.m2/repository/commons-io/commons-io/2.6/commons-io-2.6.jar:
~/.m2/repository/com/thoughtworks/xstream/xstream/1.4.10/xstream-1.4.10.jar:
~/.m2/repository/xmlpull/xmlpull/1.1.3.1/xmlpull-1.1.3.1.jar:
~/.m2/repository/xpp3/xpp3_min/1.1.4c/xpp3_min-1.1.4c.jar:
~/.m2/repository/javax/xml/bind/jaxb-api/2.3.1/jaxb-api-2.3.1.jar:
~/.m2/repository/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar:
~/.m2/repository/org/openjfx/javafx-media/11/javafx-media-11.jar:
~/.m2/repository/org/openjfx/javafx-media/11/javafx-media-11-linux.jar:
~/.m2/repository/org/springframework/spring-context/5.1.2.RELEASE/spring-context-5.1.2.RELEASE.jar:
~/.m2/repository/org/springframework/spring-aop/5.1.2.RELEASE/spring-aop-5.1.2.RELEASE.jar:
~/.m2/repository/org/springframework/spring-expression/5.1.2.RELEASE/spring-expression-5.1.2.RELEASE.jar:
~/.m2/repository/org/springframework/spring-oxm/5.1.2.RELEASE/spring-oxm-5.1.2.RELEASE.jar:
~/.m2/repository/com/google/guava/guava/24.1-jre/guava-24.1-jre.jar:
~/.m2/repository/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.jar:
~/.m2/repository/org/checkerframework/checker-compat-qual/2.0.0/checker-compat-qual-2.0.0.jar:
~/.m2/repository/com/google/errorprone/error_prone_annotations/2.1.3/error_prone_annotations-2.1.3.jar:
~/.m2/repository/com/google/j2objc/j2objc-annotations/1.1/j2objc-annotations-1.1.jar:
~/.m2/repository/org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.jar:
~/development/intellij/OpenPatrician/OpenPatricianJavaFX/target/classes:
~/development/intellij/OpenPatrician/OpenPatricianGameEvent/target/classes:
~/development/intellij/OpenPatrician/OpenPatricianClientServerInterface/target/classes:
~/.m2/repository/org/springframework/boot/spring-boot-starter-aop/2.1.0.RELEASE/spring-boot-starter-aop-2.1.0.RELEASE.jar:
~/.m2/repository/org/springframework/boot/spring-boot-starter/2.1.0.RELEASE/spring-boot-starter-2.1.0.RELEASE.jar:
~/.m2/repository/org/yaml/snakeyaml/1.23/snakeyaml-1.23.jar:
~/.m2/repository/org/aspectj/aspectjweaver/1.9.2/aspectjweaver-1.9.2.jar:
~/development/intellij/OpenPatrician/OpenPatricianServer/target/classes:
~/development/intellij/OpenPatrician/OpenPatricianEngine/target/classes:
~/.m2/repository/com/carrotsearch/hppc/0.7.2/hppc-0.7.2.jar:
~/.m2/repository/org/springframework/spring-core/5.1.2.RELEASE/spring-core-5.1.2.RELEASE.jar:
~/.m2/repository/org/springframework/spring-jcl/5.1.2.RELEASE/spring-jcl-5.1.2.RELEASE.jar:
~/.m2/repository/org/reflections/reflections/0.9.11/reflections-0.9.11.jar:
~/.m2/repository/org/javassist/javassist/3.21.0-GA/javassist-3.21.0-GA.jar:
~/development/intellij/OpenPatrician/OpenPatricianData/target/classes:
~/.m2/repository/org/projectlombok/lombok/1.18.2/lombok-1.18.2.jar:
~/.m2/repository/org/springframework/boot/spring-boot-devtools/2.1.0.RELEASE/spring-boot-devtools-2.1.0.RELEASE.jar:
~/.m2/repository/org/springframework/boot/spring-boot/2.1.0.RELEASE/spring-boot-2.1.0.RELEASE.jar:
~/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.1.0.RELEASE/spring-boot-autoconfigure-2.1.0.RELEASE.jar 
ch.sahits.game.openpatrician.standalone.OpenPatricianApplication

我遇到了这个错误:

Exception in thread "JavaFX Application Thread" java.lang.IllegalAccessError: class com.sun.media.jfxmediaimpl.NativeMediaManager (in unnamed module @0x4d7be377) cannot access class com.sun.glass.utils.NativeLibLoader (in module javafx.graphics) because module javafx.graphics does not export com.sun.glass.utils to unnamed module @0x4d7be377
    at com.sun.media.jfxmediaimpl.NativeMediaManager.lambda$new$0(NativeMediaManager.java:136)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.media.jfxmediaimpl.NativeMediaManager.<init>(NativeMediaManager.java:107)
    at com.sun.media.jfxmediaimpl.NativeMediaManager$NativeMediaManagerInitializer.<clinit>(NativeMediaManager.java:78)
    at com.sun.media.jfxmediaimpl.NativeMediaManager.getDefaultInstance(NativeMediaManager.java:90)
    at com.sun.media.jfxmedia.MediaManager.canPlayProtocol(MediaManager.java:78)
    at com.sun.media.jfxmedia.locator.Locator.<init>(Locator.java:239)
    at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.<init>(NativeMediaAudioClip.java:53)
    at com.sun.media.jfxmediaimpl.NativeMediaAudioClip.load(NativeMediaAudioClip.java:63)
    at com.sun.media.jfxmediaimpl.AudioClipProvider.load(AudioClipProvider.java:66)
    at com.sun.media.jfxmedia.AudioClip.load(AudioClip.java:135)
    at javafx.scene.media.AudioClip.<init>(AudioClip.java:83)
    at ch.sahits.game.openpatrician.sound.impl.LoopTrack.lambda$new$0(LoopTrack.java:26)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
    at java.base/java.lang.Thread.run(Thread.java:834)

据我了解,我的模块设置有问题,但我不清楚我需要更改什么:

--add-modules 添加其他模块,以及添加哪些? 将--add-opens 添加到带有哪些模块的命令中 完全不同的东西?

【问题讨论】:

【参考方案1】:

TL;DR:您需要确保 javafx.media 被解析为模块路径中的模块。您可以通过以下任一方式执行此操作:

    将其包含在 VM 参数中:--add-modules javafx.controls,javafx.media 或者使您自己的代码模块化,将适当的requires javafx.media; 指令添加到您的模块描述符中,然后使用--module 来启动您的应用程序。

如果您不确定在 IDE 和/或构建工具中如何或在何处设置 VM 参数,请查看Getting Started with JavaFX。


问题

该错误与 Java 9 中添加的 Java 平台模块系统 有关。如果您不知道什么是模块以及它们如何工作,请查看此博客:Understanding Java 9 Modules。以下是一小段摘录:

模块化在包之上增加了更高级别的聚合。关键的新语言元素是模块——一组唯一命名、可重用的相关包,以及资源(如图像和 XML 文件)和指定的模块描述符

模块名称 模块的依赖关系(即该模块依赖的其他模块) 它明确使其他模块可用的包(模块中的所有其他包对其他模块隐式不可用) 它提供的服务 它使用的服务 它允许反射到哪些其他模块

随着模块的引入,JavaFX 也被模块化了。它现在由七个模块组成,如its Javadoc 所示。这些模块在它们之间共享一些内部结构,但不与应用程序开发人员共享。这是通过qualifiedexports/opens 指令完成的。

你的错误

这是你的错误:

java.lang.IllegalAccessError: class com.sun.media.jfxmediaimpl.NativeMediaManager (in unnamed module @0x4d7be377) cannot access class com.sun.glass.utils.NativeLibLoader (in module javafx.graphics) because module javafx.graphics does not export com.sun.glass.utils to unnamed module @0x4d7be377

它告诉您未命名模块中的一个类正在尝试访问另一个命名模块中的一个类:javafx.graphics。但是,后一个模块不会将所需的包导出到至少未命名的模块。查看错误消息和给定的类名,我们可以推断出未命名模块中的类是 JavaFX 媒体实现的一部分。这表明类应该javafx.media 模块中。那为什么报错会提到未命名的模块呢?

未命名模块是类路径上所有类所属的模块。这意味着javafx.media 模块被放置在类路径中并且失去了它的身份。这样做的结果是,由javafx.graphics 模块声明的所有合格的导出/打开指令授予javafx.media 模块必要的访问权限不再适用——因此IllegalAccessError

但是...您使用了模块路径

从您在问题中提供的命令行中,我们可以看到 javafx-media-11.jar 文件已放置在模块路径 (-p) 上。那么问题是什么?问题是由于将媒体 JAR 文件放置在 both 模块路径 类路径上,同时未能确保 javafx.media 模块被解析为模块。

java.lang.module 包文档描述了模块解析的算法。基本上,它从一组根模块开始,然后递归地枚举 requires 指令。根模块由--add-modules--module 参数确定。你的代码不是模块化的,这意味着你不使用--module,你有:

--add-modules javafx.controls,javafx.graphics

换句话说,没有一个根模块直接或间接需要javafx.media 模块,因此它永远不会被解析。由于这些类也在类路径上,因此它们仍然可以找到,但现在位于未命名的模块中。如果您还没有将 JavaFX 依赖项放在类路径上,那么您将获得 ClassNotFoundException


解决方案

解决方案很简单:确保javafx.media 模块已解析。至少有两种方法可以做到这一点:

    将模块包含在您的 --add-modules 参数中。

    --add-modules javafx.controls,javafx.media
    

    请注意,您不需要指定 javafx.graphics 模块,因为它会被其他模块隐式拉入; javafx.controlsjavafx.media 都需要 javafx.graphics。在这种情况下,同样的一般推理也适用于 javafx.base 模块。

    Getting Started with JavaFX 指南展示了如何在每个主要 IDE(即 IntelliJ、Eclipse 和 NetBeans)和构建工具(即 Maven 和 Gradle)中为 JavaFX 配置 VM 选项。

    使您自己的代码模块化并添加必要的需求指令。

    module app 
        requires javafx.controls;
        requires javafx.media;
    
        // replace with your Application class' package
        exports com.example.app to javafx.graphics;
    
    

    然后确保使用--module 启动您的应用程序。

    注意对javafx.graphics 的合格导出。 This is required 以便 JavaFX 反射地实例化您的应用程序类。有类似的要求(合格的opens)for FXML controllers 和其他需要私有反射访问的 API。

还有另一种选择:将所有内容放在类路径中,包括 JavaFX 模块,并完全忽略 JPMS 模块。如果您这样做,您的主类不得Application 的子类。您必须创建一个单独的启动器类来简单地启动 JavaFX。 警告:这种方法是not supported

【讨论】:

这条简单的线结束了我的痛苦,我正在使用 Windows 10 JavaFx 11 --module-path $PATH_TO_FX --add-modules=javafx.controls,javafx.fxml,javafx .媒体【参考方案2】:

如果您使用的是VSCode,这里有一个简单的解决方案:

在java项目中存在一个名为.vscode的文件夹,其中存在一个名为launch.json的.json文件。

目录: Image

launch.json:


    "version": "0.2.0",
    "configurations": [
        
            "type": "java",
            "name": "Launch Main",
            "request": "launch",
            "vmArgs": "--module-path /Users/ASUS/javafx-sdk-16/lib --add-modules javafx.controls,javafx.fxml",
            "mainClass": "main.java.Main",
            "projectName": "MorseJavaFx_41229da3"
        ,
        
            "type": "java",
            "name": "Launch Current File",
            "request": "launch",
            "mainClass": "$file"
        
    ]

因此,在“vmArgs”行中,您必须将javafx.media 添加到最后和引号内,如下所示:

"vmArgs": "--module-path /Users/ASUS/javafx-sdk-16/lib --add-modules javafx.controls,javafx.fxml, javafx.media"

享受吧。?

【讨论】:

以上是关于运行 JavaFx 媒体应用程序时出现模块错误的主要内容,如果未能解决你的问题,请参考以下文章

JavaFX 11:创建标签时出现 IllegalAccessError

Gradle OpenJFx11:错误 - 缺少 JavaFx 运行时组件

无法将媒体特定样式应用于禁用 Javascript 时出现的错误页面

归档时出现“没有这样的模块‘翠鸟’”错误

在使用 React Native 的 IOS 运行时出现“未处理的 JS 异常:本机模块不能为空”错误

仅在访问媒体文件时出现 Cors Header 错误,应用程序的其余部分工作正常(DRF、pythonanywhere、React)