Error de módulo al ejecutar la aplicación multimedia JavaFx

Resuelto hotzst asked hace 6 años • 3 respuestas

Cuando ejecuto mi JavaFXaplicación 11 con el siguiente comando:

/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

Me encuentro con este error:

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)

Según tengo entendido, hay algún problema con la configuración de mi módulo, pero no tengo claro qué debo cambiar:

  • ¿Agregar módulos adicionales a --add-modulesy cuáles?
  • Agregar --add-opensal comando con qué módulos
  • ¿Algo completamente diferente?
hotzst avatar Nov 10 '18 15:11 hotzst
Aceptado

TL;DR: Debe asegurarse de javafx.mediaque se resuelva como un módulo desde la ruta del módulo. Puedes hacer esto mediante:

  1. Incluyéndolo en los argumentos de VM:--add-modules javafx.controls,javafx.media

  2. O hacer que su propio código sea modular, agregar una requires javafx.media;directiva apropiada al descriptor de su módulo y usarla --modulepara iniciar su aplicación.

  3. O usando un JDK que incluya JavaFX.

Si no está seguro de cómo o dónde configurar los argumentos de VM en su IDE y/o herramienta de compilación, consulte Introducción a JavaFX .


El problema

El error está relacionado con Java Platform Module System , agregado en Java 9. Si no sabe qué son los módulos y cómo funcionan, consulte este blog: Comprensión de los módulos de Java 9 . Aquí hay un pequeño extracto:

La modularidad agrega un mayor nivel de agregación por encima de los paquetes. El elemento clave del nuevo lenguaje es el módulo: un grupo reutilizable de paquetes relacionados con un nombre exclusivo, así como recursos (como imágenes y archivos XML) y un descriptor de módulo que especifica

  • el nombre del módulo
  • las dependencias del módulo (es decir, otros módulos de los que depende este módulo)
  • los paquetes que explícitamente pone a disposición de otros módulos (todos los demás paquetes en el módulo implícitamente no están disponibles para otros módulos)
  • los servicios que ofrece
  • los servicios que consume
  • a qué otros módulos permite la reflexión

Con la introducción de módulos, JavaFX también se modularizó. Ahora está compuesto por siete módulos, como puede verse en su Javadoc . Estos módulos comparten algunos de sus componentes internos entre ellos, pero no con los desarrolladores de aplicaciones. Esto se logra a través de directivas calificadas de exportación/apertura.

Tu error

Este es tu error:

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

Le indica que una clase en el módulo sin nombre está intentando acceder a una clase en un módulo con nombre diferente: javafx.graphics. Sin embargo, el último módulo no exporta el paquete necesario al menos al módulo sin nombre. Al observar el mensaje de error y los nombres de clase dados, podemos deducir que la clase en el módulo sin nombre es parte de la implementación de medios de JavaFX. Esto sugiere que la clase debería estar en el javafx.mediamódulo. Entonces, ¿por qué el error menciona el módulo sin nombre?

El módulo sin nombre es el módulo al que pertenecen todas las clases en la ruta de clases. Lo que esto significa es que el javafx.mediamódulo se colocó en el class-path y perdió su identidad. Una consecuencia de esto es que todas las directivas de exportaciones/aperturas calificadas declaradas por el javafx.graphicsmódulo que le otorgan javafx.mediael acceso necesario ya no se aplican; de ahí el IllegalAccessError.

Pero... Usaste la ruta del módulo

Desde la línea de comando que proporcionó en su pregunta, podemos ver que el javafx-media-11.jararchivo se colocó en la ruta del módulo ( -p). Entonces, ¿cuál es el problema? El problema se debe a que el archivo JAR multimedia se coloca tanto en la ruta del módulo como en la ruta de clase, y al mismo tiempo no se garantiza que el javafx.mediamódulo se resuelva como un módulo.

El algoritmo para la resolución del módulo se describe en la java.lang.moduledocumentación del paquete. Básicamente, comienza con un conjunto de módulos raíz y luego enumera recursivamente las directivas requeridas. Los módulos raíz están determinados por los argumentos --add-modulesy --module. Su código no es modular, lo que significa que no usa --moduley tiene:

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

En otras palabras, ninguno de los módulos raíz requiere directa o indirectamente el javafx.mediamódulo, por lo que nunca se resuelve. Dado que las clases también están en la ruta de clases, todavía se encuentran, pero ahora en el módulo sin nombre. Si no hubiera colocado también las dependencias de JavaFX en la ruta de clase, entonces obtendría un archivo ClassNotFoundException.


La solución

La solución es simple: asegúrese de que el javafx.mediamódulo esté resuelto. Hay al menos tres maneras de lograr esto:

(1) Incluir el módulo en el --add-modulesargumento

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

Tenga en cuenta que no necesita especificar el javafx.graphicsmódulo, ya que los otros módulos lo incorporarán implícitamente; ambos javafx.controlsy javafx.mediarequieren javafx.graphics. javafx.baseEl mismo razonamiento general se aplica en este caso también al módulo.

Las guías de Introducción a JavaFX muestran cómo configurar las opciones de VM para JavaFX en cada uno de los principales IDE (es decir, IntelliJ, Eclipse y NetBeans) y herramientas de compilación (es decir, Maven y Gradle).

(2) Haga su propio código modular

module app {
    requires javafx.controls;
    requires javafx.media;

    // replace with your Application class' package
    exports com.example.app to javafx.graphics;
}

Luego, asegúrese de iniciar su aplicación --module(espero que las versiones modernas de IDE y herramientas de compilación lo hagan por usted si su código tiene un module-infodescriptor).

Observe las exportaciones calificadas a javafx.graphics. Esto es necesario para que JavaFX cree una instancia reflexiva de su clase de aplicación. Existen requisitos similares (calificados opens) para los controladores FXML y otras API que requieren acceso reflexivo privado.

(3) Utilice un JDK que incluya JavaFX

Dado que JavaFX forma parte de la imagen en tiempo de ejecución, siempre se resolverá como módulos con nombre. Hay dos distribuciones de OpenJDK que incluyen OpenJFX que yo sepa:

  1. BellSoft Liberica (asegúrese de descargar "Full JDK")

  2. Azul Zulu (asegúrate de descargar "JDK FX")

Tenga en cuenta que también es posible crear su propio JDK mediantejlink .

"Solución" de rebotes

Advertencia: este enfoque no es compatible .

Hay otra opción: colocar todo en la ruta de clase, incluidos los módulos JavaFX, e ignorar los módulos JPMS por completo. Si hace esto, su clase principal no debe ser una subclase de Application. Tendría que crear una clase de iniciador separada que simplemente inicie JavaFX.


Si usa Maven, puede ver cómo confiar en el módulo multimedia JavaFX aquí como una dependencia aquí:

  • Importación del reproductor multimedia JavaFX (Maven)
Slaw avatar Nov 10 '2018 09:11 Slaw

Si está utilizando VSCode, aquí tiene una solución simple a su problema:

En el proyecto java existe una carpeta llamada .vscode, dentro de esta existe un archivo .json llamado launch.json.

directorio: Imagen

lanzamiento.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}"
        }
    ]
}

Entonces, en la línea " vmArgs", debes agregar javafx.mediaal final y dentro de las comillas, así:

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

Disfruta.😄

Julian Acosta avatar May 14 '2021 00:05 Julian Acosta