La comprensión de cómo afecta a la clase principal JPMS

S Sebastian:

Tengo una aplicación JavaFX muy básico que funciona a la perfección si la clase de aplicación es no la clase principal:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;

public class Main {

    public static void main(String[] args) {
        Application.launch(App.class, args);
    }

}

public class App extends Application {

    @Override
    public void start(Stage primaryStage) {
        FXMLLoader loader = new FXMLLoader(); // works
    }

}

Sin embargo, cuando fusionar las dos juntas (que es la forma recomendada en la mayoría de los tutoriales, incluyendo la documentación oficial de OpenJFX ), el sistema de módulos lanza una IllegalAccessError(al menos en OpenJDK 11.0.2):

public class MainApp extends Application {

    @Override
    public void start(Stage primaryStage) {
        FXMLLoader loader = new FXMLLoader(); // throws IllegalAccessError
    }

    public static void main(String[] args) {
        launch(MainApp.class, args);
    }

}

La excepción es:

java.lang.IllegalAccessError: clase com.sun.javafx.fxml.FXMLLoaderHelper(en el módulo sin nombre @0x642c1a1b) no puede clase de acceso com.sun.javafx.util.Utils(en el módulo javafx.graphics), porque el módulo javafx.graphicsno exportar com.sun.javafx.utilal módulo sin nombre@0x642c1a1b

Lo extraño es, que no utilizan activamente el sistema de módulos. No añadí una module-info.javaa mi proyecto. Así que supuse que todo debe conseguir exportado a cualquier módulo sin nombre? Pero eso no es ni siquiera el punto.

La cuestión principal es: ¿Por qué se comportan del mismo código diferente si distribuye a través de dos clases? En ambos casos, FXMLLoaderlos usos com.sun.javafx.fxml.FXMLLoaderHelper, los cuales a su vez en usos com.sun.javafx.util.Utils. Así que, o que debería obtener la excepción en ambos casos o en ninguno. ¿Cuál es la diferencia?

José Pereda :

Hay algunas respuestas que habían puesto que podría aplicarse en parte a sus preguntas, pero podría ser conveniente recogerlos aquí y presentarlos de una respuesta completa.

clase de aplicación

En la respuesta a Maven sombra componentes de ejecución de JavaFX se echa en falta me explicó la razón por la cual, cuando se utiliza la Applicationclase como su clase principal, se espera que utilice el sistema de módulos.

En resumen:

Como se puede leer aquí :

Este error proviene de sun.launcher.LauncherHelperen el módulo java.base ( enlace ).

Si la aplicación principal se extiende Applicationy tiene un mainmétodo, la LauncherHelpercomprobaremos para el javafx.graphicsmódulo para estar presente como un módulo denominado:

Optional<Module> om = ModuleLayer.boot().findModule(JAVAFX_GRAPHICS_MODULE_NAME);
if (!om.isPresent()) {
    abort(null, "java.launcher.cls.error5");
}

Si ese módulo no está presente, el lanzamiento se aborta.

Cada frasco de JavaFX 11 tiene un module-info.classarchivo, por lo que, por definición, se espera que éstos se añade a la ruta del módulo.

Pero si no se ejecutan a través de Applicationla clase, que el registro no se realiza.

Clase principal

Esta otra respuesta a un comportamiento diferente entre Maven y Eclipse para lanzar una aplicación JavaFX 11 explica por qué funciona sin el sistema modular cuando se utiliza una Launcherclase (una clase principal que no se extiende Aplicación) con el Maven exec:javaplugin.

En resumen:

  • El uso de un lanzador se requiere para superar el mencionado sun.launcher.LauncherHelpertema.
  • Al igual que los plugin se ejecuta maven en la ruta de clase, cargando todas las dependencias en una rosca aislado, lo mismo ocurre con IntelliJ en este caso.

Si marca la línea de comandos al ejecutar Main.main():

/path/to/jdk-11.0.2.jdk/Contents/Home/bin/java \
    "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=60556:/Applications/IntelliJ IDEA.app/Contents/bin"  \
    -Dfile.encoding=UTF-8  \
    -classpath /path/to/so-question-54756176-master/target/classes:/path/to/.m2/repository/org/openjfx/javafx-base/11.0.2/javafx-base-11.0.2.jar:.../path/to/.m2/repository/org/openjfx/javafx-fxml/11.0.2/javafx-fxml-11.0.2-mac.jar  \
    Main

Todos los frascos de JavaFX JavaFX SDK se añaden a la ruta de clase, y está ejecutando el clásico java -cp ... Main.

javafx.fxml falta

Estos otra respuesta a IntelliJ IDEA - Error: componentes de ejecución de JavaFX se echa en falta, y se requieren para ejecutar esta aplicación se explica el error que se obtiene cuando se ejecuta en el sistema de módulos, pero no se agrega javafx.fxmla la --add-modulesopción.

Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x5fce9dc5) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x5fce9dc5
    at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
    at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2056)

Su error dice que está utilizando FXML pero no se puede resolver en el módulo de la ruta, por lo que está intentando acceder a través de la reflexión y que no logra ya que usted no abrió que javafx.graphicsa su módulo sin nombre.

Así que ahora usted se preguntará: Yo no puse el javafx.graphicsen el primer lugar!

Bueno, no lo hizo, pero IntelliJ lo hizo por ti!

Compruebe la línea de comandos al ejecutar MainApp.main():

/path/to/jdk-11.0.2.jdk/Contents/Home/bin/java \
    --add-modules javafx.base,javafx.graphics \
    --add-reads javafx.base=ALL-UNNAMED \
    --add-reads javafx.graphics=ALL-UNNAMED \
    "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=60430:/Applications/IntelliJ IDEA.app/Contents/bin" \
    -Dfile.encoding=UTF-8 \
    -classpath /path/to/so-question-54756176-master/target/classes:/path/to/.m2/repository/org/openjfx/javafx-base/11.0.2/javafx-base-11.0.2.jar:.../.m2/repository/org/openjfx/javafx-graphics/11.0.2/javafx-graphics-11.0.2-mac.jar \
    MainApp

Se puede ver que IntelliJ agrega de forma predeterminada javafx.basey javafx.graphics. Por lo que sólo la javafx.fxmlfalta (y entonces usted debe, por supuesto, añadir el módulo de ruta).

La solución recomendada, como usted ha señalado, se encuentra en los documentos :

Ya sea en la línea de comandos, utilizando --module-pathpara incluir la ruta de la carpeta de la liberación de JavaFX SDK, y --add-modulespara incluir javafx.fxmlen este caso (en el que no tiene controles).

IntelliJ argumentos VM

O usando el plugin de Maven. En algún momento tendrá que salir de su IDE, por lo que tendrá que utilizar un plugin para ejecutar la aplicación.

ejecución Maven

Una nota final sobre el Maven execplugin, en caso de que se utilice:

Lo que es más, la solución Maven recomendada, hasta que el complemento exec:javase fija para el sistema modular (y la noticia buena es que esto está siendo hecho en estos momentos ), va a utilizar exec:execen su lugar, como se explica en este tema , por lo que puede especificar tanto vm argumentos.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=173340&siteId=1
Recomendado
Clasificación