Module error when running JavaFx media application
TL;DR: You need to make sure javafx.media
is resolved as a module from the module-path. You can do this by either:
- Including it in the VM arguments:
--add-modules javafx.controls,javafx.media
- Or making your own code modular, adding an appropriate
requires javafx.media;
directive to your module descriptor, and using--module
to launch your application.
If you're not sure how or where to set the VM arguments in your IDE and/or build tool, check out Getting Started with JavaFX.
The Problem
The error is related to the Java Platform Module System, added in Java 9. If you're not aware of what modules are and how they work, check out this blog: Understanding Java 9 Modules. Here's a small excerpt:
Modularity adds a higher level of aggregation above packages. The key new language element is the module—a uniquely named, reusable group of related packages, as well as resources (such as images and XML files) and a module descriptor specifying
- the module’s name
- the module’s dependencies (that is, other modules this module depends on)
- the packages it explicitly makes available to other modules (all other packages in the module are implicitly unavailable to other modules)
- the services it offers
- the services it consumes
- to what other modules it allows reflection
With the introduction of modules, JavaFX was also modularized. It is now made up of seven modules, as can be seen by its Javadoc. These modules share some of their internals between themselves, but not with application developers. This is accomplished through qualified exports/opens directives.
Your Error
This is your 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
It's telling you a class in the unnamed module is attempting to access a class in a different, named module: javafx.graphics
. However, the latter module does not export the needed package to at least the unnamed module. Looking at the error message and the given class names, we can deduce that the class in the unnamed module is part of JavaFX's media implementation. This suggests the class should be in the javafx.media
module. Then why does the error mention the unnamed module?
The unnamed module is the module all classes on the class-path belong to. What this means is that the javafx.media
module was put on the class-path and lost its identity. A consequence of this is that all the qualified exports/opens directives declared by the javafx.graphics
module which grant the javafx.media
module the necessary access no longer apply—hence the IllegalAccessError
.
But... You Used the Module-Path
From the command line you provided in your question we can see the javafx-media-11.jar
file was placed on the module-path (-p
). So what is the problem? The problem is caused by placing the media JAR file on both the module-path and the class-path, while simultaneously failing to ensure the javafx.media
module is resolved as a module.
The algorithm for module resolution is described by the java.lang.module
package documentation. Basically, it starts with a set of root modules and then recursively enumerates the requires directives. The root modules are determined by the --add-modules
and --module
arguments. Your code isn't modular, meaning you don't use --module
, and you have:
--add-modules javafx.controls,javafx.graphics
In other words, none of the root modules directly or indirectly require the javafx.media
module, thus it is never resolved. Since the classes are also on the class-path they're still found, but now in the unnamed module. If you had not placed the JavaFX dependencies on the class-path as well then you'd be getting a ClassNotFoundException
.
The Solution
The solution is simple: Make sure the javafx.media
module is resolved. There are at least two ways to accomplish this:
Include the module in your
--add-modules
argument.--add-modules javafx.controls,javafx.media
Note you don't need to specify the
javafx.graphics
module as it'll be pulled in implicitly by the other modules; bothjavafx.controls
andjavafx.media
requirejavafx.graphics
. The same general reasoning also applies to thejavafx.base
module in this case.The Getting Started with JavaFX guides show how to configure the VM options for JavaFX in each of the major IDEs (i.e. IntelliJ, Eclipse, and NetBeans) and build tools (i.e. Maven and Gradle).
Make your own code modular and add the necessary requires directives.
module app {
requires javafx.controls;
requires javafx.media;
// replace with your Application class' package
exports com.example.app to javafx.graphics;
}Then make sure to launch your application with
--module
.Notice the qualified exports to
javafx.graphics
. This is required in order for JavaFX to reflectively instantiate your application class. There are similar requirements (qualifiedopens
) for FXML controllers and other APIs which require private reflective access.
There is another option: Place everything on the class-path, including the JavaFX modules, and ignore JPMS modules completely. If you do this your main-class must not be a subclass of Application
. You'd have to create a separate launcher class that simply launches JavaFX. Warning: This approach is not supported.
If you use Maven, you can see how to rely on the JavaFX media module here as a dependency here:
- JavaFX media player import (Maven)
Java FX Modular Application, Module not found (Java 17, Intellij)
Steps to address your issue
- Ensure that you are using the most recent stable version of Idea (currently 2021.3.2), Java and JavaFX (currently 17.0.2).
- Discard your current project.
- Create a new project.
- Follow the instructions at Create a new JavaFX project provided by Idea on how to use their wizard.
- If you follow the instructions exactly it should work.
- You don't need to add "the Java FX lib" to the project manually.
- The wizard will create a dependency in Maven or Gradle which includes the most common JavaFX modules.
- You don't need to download or use the JavaFX SDK mentioned at openjfx.io.
- You don't need to explicitly set any VM arguments such as
--add-modules
the wizard will create the amodule-info.java
file which references the modules.
Before proceeding any further, make sure that the basic generated project build and runs in your environment (according to the build and execution instructions documented by IntelliJ for the new JavaFX project wizard).
Using additional JavaFX modules
If you want to use additional JavaFX modules (e.g. javafx.media or javafx.web):
- Add the additional modules manually to the maven or gradle build file.
- Reimport the build file into the Idea project.
- Add requires clauses form the modules to the module-info.java.
Making your application non-modular
Even if your application is made non-modular, you still need to have JavaFX modules on the module path as that is the only way the execution of JavaFX is supported.
If you don't want a modular application, you can delete the module-info.java file and manually add VM arguments for the module path to the JavaFX and an --add-modules
switch.
I do not advise doing this step unless:
- You have a good reason not to have a non-modular application (e.g. rely on 3rd party dependencies which do not integrate easily with the Java module system), AND
- You have knowledge about how to make non-modular JavaFX applications.
Cause of the module find exception
The reason for your specific error:
java.lang.module.FindException: Module com.example.hudrava_test not found
is because you don't have module-info.java
for a module with that name on the module path. Note that is not a JavaFX module name, but something you have specified. You have tried to run the application by specifying a class name within the non-existent module, e.g.
java --module-path <somepath> -m com.example.hudrava_test/com.example.hudrava_test.HelloApplication
You can find out further info about that in:
- java.lang.module.FindException: Module not found.
However, you should not need to manually take the steps outlined in that answer, because, when you create a new project using the new JavaFX wizard, it will automatically create a module-info.java file and place your application's build output on the modulepath.
So the error was caused by something you did after creating the project with the wizard (I don't know what). When you create a new project, you should not have the error.
On module naming and underscores
The Jenkov module tutorial states:
A Java module name follows the same naming rules as Java packages. However, you should not use underscores (_) in module names (or package names, class names, method names, variable names etc.) from Java 9 and forward, because Java wants to use underscore as a reserved identifier in the future.
It is recommended to name a Java module the same as the name of the root Java package contained in the module - if that is possible (some modules might contain multiple root packages).
So, it is inadvisable to have underscores in either your module or your package name.
More info on module naming suggestions is provided in:
- How should I name my Java 9 module?
Problem starting my application using JavaFX
I had similar issue. For me solution was to
add following configuration :
--add-modules javafx.controls,javafx.fxml
insted of just
--add-modules javafx.controls
Javafx MediaPlayer runs into error whenever you disconnect bluetooth headphones
The problem with your recovery is that you are seeking too soon. The docs for seek state that it does nothing while the media player is stopped, but you aren't waiting for the state to change after calling play().
Try this:
mediaPlayer.setOnError( () -> {
mediaPlayer = new MediaPlayer(media);
System.out.println(durationBackup.toMillis());
mediaPlayer.setOnPlaying(() ->{
mediaPlayer.seek(durationBackup);
mediaPlayer.setOnPlaying(null);
});
mediaPlayer.play();
});
JavaFX MediaPlayer import
If you define a module-info.java
file and you want to use the javafx.media
module, you need to require that module in your module-info (as suggested by kleopatra in comments).
module com.example.demo {
requires javafx.controls;
requires javafx.fxml;
requires javafx.media;
opens com.example.demo to javafx.fxml;
exports com.example.demo;
}
The JavaFX modules are named in the javadoc.
Oracle provide a brief introduction to the module system, which you should understand when you use it.
As you are using Maven and JavaFX 17.0.0.1, you also need a dependency in Maven on that version of the javafx-media module.
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>17.0.0.1</version>
</dependency>
For a full discussion of this topic, see:
- Module error when running JavaFx media application
JavaFX trouble importing
As javaFX is already bundled with JDK 8. I would suggest, try using java 8 instead, if it works, then your previous setup wasn't correct.
Related Topics
How to Rotate an Image Gradually in Swing
Swing Grouplayout: Resizing and Limiting Component Sizes
It Is a Bad Practice to Use Sun's Proprietary Java Classes
What's the Difference Between Fx:Id and Id: in Javafx
Using Prepared Statements to Set Table Name
Jtable Not Showing Up on Jframe (Java)
Jsp Tricks to Make Templating Easier
How to Initialise a Static Map
How to Use Optional Parameters in Java
How to Get the Current Date/Time in Java
What Is the Point of "Final Class" in Java
Why Doesn't Java Offer Operator Overloading
How to Implement Constants in Java
How to Map a Composite Key with JPA and Hibernate
Can Enums Be Subclassed to Add New Elements
Does Use of Final Keyword in Java Improve the Performance