How to Mix --Class-Path and --Module-Path in Javac (Jdk 9)

Is it possible to mix --class-path and --module-path in javac (JDK 9)?

You can use class path and module path in parallel, but there are a few details to consider.

Dependency Module Path ~> Class Path

Explicit modules (JARs with a module descriptor on the module path) can not read the unnamed module (JARs on the class path) - that was done on purpose to prevent modular JARs from depending on "the chaos of the class path".

Since a module must require all of its dependencies and those can only be fulfilled by other named modules (i.e. not JARs on the class path) all dependencies of a modular JAR must be placed on the module path. Yes, even non-modular JARs, which will then get turned into automatic modules.

The interesting thing is that automatic modules can read the unnamed module, so their dependencies can go on the class path.

Dependency Class Path ~> Module Path

If you compile non-modular code or launch an application from a non-modular JAR, the module system is still in play and because non-modular code does not express any dependencies, it will not resolve modules from the module path.

So if non-modular code depends on artifacts on the module path, you need to add them manually with the --add-modules option. Not necessarily all of them, just those that you directly depend on (the module system will pull in transitive dependencies) - or you can use ALL-MODULE-PATH (check the linked post, it explains this in more detail).

modulepath environment variable in Java similar to CLASSPATH

No, the jdk does not read any MODULEPATH environment variable or similar.

The MODULEPATH only exists as a command-line argument --module-path, but not as an environment variable.

See http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-September/009345.html

Unlike CLASSPATH, there is no equivalent MODULEPATH to get the option off of the command line.

Also see the linked question Is it possible to mix --class-path and --module-path in javac (JDK 9)? for more details on the differences between boths paths.

If you put a normal jar on the modulepath, it becomes an automatic module, exporting its packages (and reserving those packages for itself).

While you can put any normal jar file into the MODULEPATH, there is a restriction: If 2 jar files contain the same package, then java will not allow both of them in the modulepath. That's why Java still has the classpath, because several existing jar files still have overlapping packages, and it is not possible to put them all on the MODULEPATH. They have to be cleaned up first.

In the far future, when all libraries have been migrated to modules (or cleaned up), maybe classpath can be removed.

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

+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.

How do you compile against a jar file in Java 9?

You misspelled the option. According to the javac options page for Java 9:

--class-path path , -classpath path, or -cp path

Specifies where to find user class files and annotation processors. This class path overrides the user class path in the CLASSPATH environment variable.

For some reason, if you use the two hyphens option --, there is a hyphen in "classpath": --class-path. The one hyphen option - has no hyphen in "classpath": -classpath.

Any of these are valid:

javac *.java --class-path junit.jar

javac *.java -classpath junit.jar

javac *.java -cp junit.jar

Is it possible to use external lib with classpath in NetBeans IDE with modular application?

Yes. A modular application’s runtime effectively ignores the classpath. This is because the everything in the classpath belongs to the unnamed module, which named modules cannot access.

This is described in detail by Is it possible to mix --class-path and --module-path in javac (JDK 9)?.

In Eclipse, what is the difference between modulepath and classpath? also contains some useful information about this.



Related Topics



Leave a reply



Submit