asker
asker

Reputation: 3

The class SwingNode in openjfx causes problems

I wanted to migrate my JavaFX app to JDK 11 & OpenJFX and I noticed that SwingNode causes problems. I decided to create new project and see what's going on. Interestingly, when I change to JDK 8, everything is fine. In newer version, errors appear. I don't know what it's due to.

package sample;

import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();

        // problem
        final SwingNode swingNode = new SwingNode();
    }


    public static void main(String[] args) {
        launch(args);
    }
}
Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/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.IllegalAccessError: superclass access check failed: class com.sun.javafx.embed.swing.SwingNodeHelper (in unnamed module @0x412b4fb) cannot access class com.sun.javafx.scene.NodeHelper (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.scene to unnamed module @0x412b4fb
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
    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:521)
    at javafx.embed.swing.SwingNode.<clinit>(SwingNode.java:143)
    at sample.Main.start(Main.java:20)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    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.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    ... 1 more
Exception running application sample.Main

VM options: --module-path ${PATH_TO_FX} --add-modules=javafx.controls,javafx.fxml

Upvotes: 0

Views: 1090

Answers (1)

Slaw
Slaw

Reputation: 46116

The important part of that stack trace is the last Caused by:, which is:

Caused by: java.lang.IllegalAccessError: superclass access check failed: class com.sun.javafx.embed.swing.SwingNodeHelper (in unnamed module @0x412b4fb) cannot access class com.sun.javafx.scene.NodeHelper (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.scene to unnamed module @0x412b4fb

This says there's a class, named SwingNodeHelper, in the "unnamed module" which extends a class, named NodeHelper, present in the javafx.graphics module. The javafx.graphics module, however, does not export this superclass (more specifically, the package to which the superclass belongs) to the "unnamed module". This leads to the IllegalAccessError when trying to load the SwingNodeHelper class.

The "unnamed module" is a special Module (one per ClassLoader) which contains the classes on the classpath. The SwingNode and related SwingNodeHelper classes are part of the javafx.swing module. This knowledge, combined with the given error, tells us the javafx.swing module is being used from the classpath when it needs to be used from the modulepath. The fix, as stated by José Pereda in a comment, is to include the javafx.swing module in your --add-modules command.

The reason this works is because the javafx.graphics modules does export the needed package to the javafx.swing module—but everything needs to be on the modulepath in order to work properly.

When, or if, you make your code modular you can forgo the --add-modules command and simply list the appropriate requires directives in your module-info.java file.

module <your-module-name> {
    requires javafx.swing;
    // other directives...
}

Related questions:

Upvotes: 3

Related Questions