Blog-Archiv

Samstag, 21. November 2020

Java Module Types

The Java Platform Module System (JPMS) defines different types of modules. This is to ease the migration from old CLASSPATH bound projects to the new module-path way. In an ideal world, just real JPMS modules exist, no other types. But, as some open-source libraries are not maintained any more and may never become modules, it is questionable whether that world will ever exist.

Type Designations

Module Type Description Can Access No Access To
Java Modules
(Named Modules,
Explicit Modules)
One or more Java packages that have a module-info.java descriptor in their root directory (dependency definitions).
Sub-types are ...
System Modules Java runtime libraries like java.base that need no requires statement to be available
Application Modules whatever your application defines as module
Service Modules a module that uses the provides keyword
Open Modules a module that uses the open keyword to allow reflection on its classes
System modules and all modules that it requires (in case it was not prohibited via exports somepackage to somemodule), also Automatic modules that it requires The Unnamed Module
Automatic Modules A Java archive (JAR) file without module-info.java that has been put on the module-path. All its packages will be exported automatically and are open for reflection. It has an automatically generated name, built from the basename of the JAR file, by which it can be required in a named module.
Legacy JARs go here.
All exported packages of modules on the module-path, also the Unnamed Module. Module packages that were not exported
The Unnamed Module Everything that is on CLASSPATH. All packages get exported automatically and are open for reflection. This module has no name, thus it can not be required by modules. All exported packages of modules on the module-path, also Automatic modules, and all packages on CLASSPATH. Module packages that were not exported

How to Use

The JDK runtime library has been modularized to System Modules. Any application that wants to upgrade to Java 9 can use them by going to the Unnamed Module, together with all its JAR dependencies (CLASSPATH). For that it is not even necessary to define a module-path.

The only drawback is the "Split Packages" constraint. Java compilers above version 9 don't accept two packages with the same name on CLASSPATH. Typical error message is

  The package javax.xml.transform is accessible from more than one module: <unnamed>, java.xml

when you have e.g. xml-apis.jar on the CLASSPATH as transitive Maven dependency. Normally this can be solved with Maven <exclusions>. The "Split Packages" constraint detects different versions of the same library, a big problem of CLASSPATH-bound applications.

As soon as you modularize your application, all JAR dependencies must go to the module-path as Automatic Modules and have to be required in module-info.java, because Named Modules can not access the Unnamed Module (CLASSPATH) any more. Running the application then will not work without --module-path option. Mind that the module-info.java descriptor can be extended through JVM commandline options like --add-modules, --add-exports, --add-reads.

The "Split Packages" constraint would not work when both CLASSPATH and module-path are active. If there were two packages with same name, one on CLASSPATH and one on module-path, the one on module-path would be silently preferred.

Conclusion

The different module types make it easy to migrate applications to a Java version above 9. CLASSPATH is represented by the Unnamed Module, Named Modules are intended to be on module-path. Like the CLASSPATH, the module-path plays a role at both compile-time and runtime. In future it will replace the CLASSPATH.

JPMS modules are made to be checked at compile-time. They can not be replaced at runtime like OSGI plugins can, they can not be started or stopped, and they do not support versioning. Their only runtime-bound behavior is the service providing via provides and uses.




Keine Kommentare: