Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @...'

Tags:

java

javafx

I just downloaded JavaFX and set it up, I have done nothing else. I ran the sample code and this was the warning that popped up, although everything compiled. I'm using IntelliJ.

This is in Main.java:

package sample;

import javafx.application.Application;
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();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

This is in sample.fxml:

<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.GridPane?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<GridPane fx:controller="sample.Controller"
          xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
</GridPane>

When running, everything compiles, the window pops up, but I get the warning as stated in the title.

I never used JavaFX before so I'm unsure of where to locate this module.

like image 677
Jon Avatar asked Jun 05 '21 21:06

Jon


People also ask

Why is JavaFX not loading from the class-path?

But now, as of version 16, a warning is emitted if JavaFX detects it was loaded from the class-path (i.e. is in the unnamed module ). See JDK-8256362. The solution is to make sure JavaFX is loaded from the module-path and resolved as named modules. Note JavaFX is made up of seven modules, as can be seen by its documentation.

Is there a way to fix JavaFX code not being modular?

This is a new thing in JavaFX 16—see JDK-8256362. The general fix is to place the JavaFX modules on the module-path and to ensure they are resolved as modules (e.g. if your code isn't modular you may need to use --add-modules ). Though note having JavaFX on the module-path does not require that your code be modular.

Does JavaFX support automatic load of named modules?

A named module may or may not be automatic, depending on if it has a module-info descriptor or not, respectively. JavaFX only supports being loaded as named modules. In other words, JavaFX only supports being loaded from the module-path, not the class-path.

Is there a way to fix the JavaFX module path problem?

Thank you for the answers in advance! This is a new thing in JavaFX 16—see JDK-8256362. The general fix is to place the JavaFX modules on the module-path and to ensure they are resolved as modules (e.g. if your code isn't modular you may need to use --add-modules ).


1 Answers

TL;DR:

Make sure JavaFX is resolved as named modules.

  • Non-modular application:

    java --module-path <path-to-fx> --add-modules <fx-modules> ...
    
  • Modular application:

    java --module-path <path> --module <main-module>/<main-class> [args...]
    

    Where <path> includes your module as well as JavaFX.

  • Use JDK distribution which includes JavaFX (see answer below for more information). May still need to use --add-modules.


Background

This warning is related to the Java Platform Module System (JPMS) introduced in Java 9. If you're not familiar with modules, then I recommend reading Understanding Java 9 Modules for a brief overview.

With JPMS came the module-path, which now exists alongside the class-path. When classes are loaded from the class-path they become a part of the so-called unnamed module. Whereas classes on the module-path are contained within modules, and are thus loaded "into" named modules. A named module may or may not be automatic, depending on if it has a module-info descriptor or not, respectively.


The Warning

JavaFX only supports being loaded as named modules. In other words, JavaFX only supports being loaded from the module-path, not the class-path. This has been implicitly true since version 9, back when the framework was modularized. But now, as of version 16, a warning is emitted if JavaFX detects it was loaded from the class-path (i.e. is in the unnamed module). See JDK-8256362.


Solution

The solution is to make sure JavaFX is loaded from the module-path and resolved as named modules. Note JavaFX is made up of seven modules, as can be seen by its documentation.

How exactly you ensure JavaFX is resolved as named modules may depend on your environment (e.g. non-modular vs modular application, external JavaFX SDK, etc.). The examples below all use the command-line to show how to set the needed arguments. However, if you're using an IDE (e.g. NetBeans, IntelliJ, Eclipse) and/or a build tool (e.g. Maven, Gradle) and are unsure of where to set these arguments, then check out Getting Started with JavaFX 11+.

Note that both Gradle and Maven have plugins that make it easier to work with JavaFX (i.e. they handle all the configuration for you).

Non-modular Application

If your code is non-modular then you do not have a module-info descriptor. This means adding JavaFX to the module-path is not enough; you also have to force Java to resolve the JavaFX modules. That can be done via the --add-modules argument.

For example:

java --module-path <path-to-fx> --add-modules javafx.controls ...

Notice I only include the javafx.controls module in the --add-modules argument. This is because it requires the javafx.base and javafx.graphics modules, which means they will be implicitly pulled in.

If you need other modules then you need to include them in the --add-modules argument as well, separated by a comma.

Also, note it's okay, in this case, to have your code and other non-modular dependencies on the class-path. The important part is that JavaFX is loaded from the module-path.

Modular Application

If your code is modular then you will have a module-info descriptor. This descriptor will have the necessary requires directives. In this case, you no longer need to use --add-modules, but you do need to make sure to launch your application as a module via --module.

For example:

module app {
  // transitively requires javafx.base and javafx.graphics
  requires javafx.controls;

  // export javafx.application.Application implementation's package
  // to at least javafx.graphics
  exports com.example.app to javafx.graphics;
}
java --module-path <path> --module app/com.example.app.Main [args...]

Note for this you need to not only put JavaFX on the module-path, but also your own module.

Use a JDK Distribution that Includes JavaFX

Since Java 11, JavaFX is no longer included in the JDK provided by Oracle. But Oracle is not the only vendor for Java based on OpenJDK. There are vendors out there that provide JDK distributions which include JavaFX. At least two of them are:

  • BellSoft Liberica JDK (make sure to choose the "Full JDK" option).
  • Azul Zulu JDK (make sure to choose the "JDK FX" package).

When JavaFX is included in the JDK, it's now part of the run-time image like all the other Java modules (e.g. java.base). This means it will automatically be loaded as named modules and you no longer have to manually put JavaFX on the module-path. However, if your application is non-modular then you may still need to use --add-modules (not sure).

Deployment

When you go to deploy a JavaFX application, including JavaFX in the run-time image is likely the easiest approach. You can do this with the jlink / jpackage tools. And this can be done with either a JDK that includes JavaFX or an external JavaFX SDK. However, if you use the latter then make sure to use the JMOD files when making the custom run-time image (or use the JavaFX JARs from Maven Central, which embed the needed native code).

If your code is non-modular, then you'd create a custom run-time image that includes JavaFX (and all the other non-automatic named modules needed by your application), and then configure jpackage to place your code (and all non-modular dependencies) on the class-path.

Ignore the Warning

As far as I can tell, nothing currently breaks if JavaFX is loaded from the class-path. This means another option, at least for now, is to just ignore the warning. However, I recommend putting at least JavaFX on the module-path if you can do so without too much trouble.

like image 65
Slaw Avatar answered Nov 02 '22 06:11

Slaw