Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is --add-modules necessary for modules which are on the module path?

An example: since JavaFx was dropped from the JDK, the JavaFx SDK is now distributed as a set of modular jars. To compile a JavaFx application, of course you have to put them on the module path:

javac -p /path/to/jars/ App.java

That doesn't suffice, however. Trying to compile will cause a lot of errors similar to

sample/App.java:3: error: package javafx.application is not visible
import javafx.application.Application;
             ^
  (package javafx.application is declared in module javafx.graphics, which is not in the module graph)

To resolve this, we can add javafx.graphics with --add-modules:

javac -p /path/to/jars/ --add-modules javafx.graphics App.java

If we added a module-info.java (containing just module ui {}) to the project instead, though, we have no issue.

Why are the modules on the module path visible to named modules but not the unnamed module?

like image 538
hat Avatar asked Jun 12 '20 09:06

hat


People also ask

What is -- add modules?

The option --add-modules $modules , which is available on javac and java , allows explicitly defining a comma-separated list of root modules beyond the initial module. (Root modules form the initial set of modules from which the module graph is built by resolving their dependencies.)

Why do we need modules in Java?

A Java module is a packaging mechanism that enables you to package a Java application or Java API as a separate Java module. A Java module is packaged as a modular JAR file. A Java module can specify which of the Java packages it contains that should be visible to other Java modules which uses this module.

What is module path in Java?

A CLASSPATH is a sequence of classes' base paths and JAR files for the Java Compiler or JVM to locate the classes used in the application. Similarly, in JDK 9, a MODULEPATH is a sequence of modules' base paths and Modular JAR files for the Java Compiler or JVM to locate the modules used in the application.

Which module is available to your named module without needing a Requires directive in Java?

xml module, code in modules that read java. desktop becomes dependent on java. xml . Without the requires transitive directive in java.


1 Answers

+1 for a very good question. The issue here is that when you compile named and unnamed modules, their default set of root modules is computed very differently.

This is a quote from JEP 261 which explains that difference:

When the compiler compiles code in the unnamed module, or the java launcher is invoked and the main class of the application is loaded from the class path into the unnamed module of the application class loader, then the default set of root modules for the unnamed module is computed as follows:

The java.se module is a root, if it exists. If it does not exist then every java.* module on the upgrade module path or among the system modules that exports at least one package, without qualification, is a root.

Every non-java.* module on the upgrade module path or among the system modules that exports at least one package, without qualification, is also a root.

This may look a bit complicated so I've put the most important parts of that text in bold. Also, let's go step by step:

  • You don't have module-info.java, so your module is an unnamed module.
  • java.se exists, so it's got into a root set.
  • Your upgrade module path is empty (because you specified only -p and not --upgrade-module-path).
  • The system modules that export at least one package also got into the set.

Therefore, the root set is only java.se and some system modules. And no JavaFX modules got into the set!

Now, what happens when you compile with module-info.java? The root set is computed using different rules:

Otherwise, the default set of root modules depends upon the phase:

At compile time it is usually the set of modules being compiled

Since the root module is your module which requires JavaFX modules, they got into the module graph.

So, how to solve the issue? You can do it either by putting JavaFX modules on the upgrade module path:

javac --upgrade-module-path /path/to/jars/ App.java

Or by using --add-modules:

javac -p /path/to/jars/ --add-modules ...

Or by using the plain old classpath:

javac -cp /path/to/jars/ App.java

All three options should work. Let me know if the first option actually works because I didn't try it.

like image 123
ZhekaKozlov Avatar answered Oct 20 '22 19:10

ZhekaKozlov