Part-2: JPMS/Java Modules - descriptor, directives, types

The section “Part-1: JPMS/Java Modules – introduction” provided a basic idea behind the Java Modules. The following section focuses on additional details related to the java module descriptor file module-info.java, its directives and also possible type of modules.

Module description (module-info.java) details

Every java module requires to have located its descriptor file module-info.java inside its module root directory. The module descriptor contains the metadata about the module dependencies and availability of internal packages to the other modules.

Java Platform Module System (JPMS) ensures that there are no possible circular dependencies inside the module graph. It means the application module graph needs to be acyclic. JPMS also checks for the packages similarities, the same package can not be exported by more modules.

JPMS “not allowed” in bullets:
  • to split packages
  • to create circular dependencies

The module descriptor starts with the keyword module followed by the unique module name.

module wits.producer {
    requires java.base;
    exports com.producer to wits.consumer; 
    uses com.producer.service.FruitService;
    provides com.producer.service.FruitService 
        with com.producer.service.FruitServiceImpl;
} 

Module directives

The multiple module directives may be used for the module declaration such as: requires, requires transitive, exports, exports…to, provides…with, uses, transitive:

requires: the directive specifies the dependency on another module. The example above wits.producer module requires java.base module to run.

requires transitive:  the transitive keyword is used to imply the dependencies of the required module. The JPMS ensures that also dependencies of the required module are read, implied readability.  The module will not compile until it explicitly reads required package.

exports: the directive allows to make visible package to the other modules. All public or protected (included nested) access types are accessible that belong to the exported package. All sub-packages remain invisible, it means sub-package are not exported.

exports… to… : similar to “exports” but the keyword “…to …” specifies to which module the package will be visible, qualified export.

uses: the directive specifies a service used by the module. It creates a module a service consumer. A service implements the interface or abstract class specified by uses keyword (see above).

provides…with…: The directive specifies that the module provides the service implementation. The 1s part “provides” describes the interface or abstract class (defined by uses directive) and the 2nd part “…with …” specifies the implementation details (see above)

open, opens and opens..to directives

Those directives are related to the strong-encapsulation concept provided by the JPMS. By default the modules and related packages are not accessible by the others.  Such open directives allow to open module or packages to other modules at the runtime. It means that all public or protected types are accessible via reflection.

open: allows runtime-only access to all packages in module

opens: allows runtime-only access to a package

opens…to: allows runtime-only access to a package by specific module

Module types overview

Named Modules

described over the sections…

Unnamed Modules

Beginning with Java SE 9 all classes are located in modules that JVM can use them. Even after the Java SE 9 the classpath option can be used. In order to compile not modularized code, all classes resides in the classpath folder.

All classes that doesn’t belong to any ‘named module’ are marked as a member of ‘unnamed module’. Such ‘unnamed module’ belongs to the unnamed ‘default package’. The ‘unnamed module’ can be seen as the ‘default module’.

Inside such classpath every unnamed module ‘requires’ all named modules implicitly. This means that every class inside the ‘default module’ can read all other modules ( named or unnamed) without any explicit declarations.  Every ‘unnamed module’ also ‘exports’ all its packages.

The impact of the “unnamed module” concept is that artifacts compiled with older Java versions or do not contain “named modules” will continue to use dependencies as before.

Automatic Modules

Automatic modules are named modules which are automatically created by not modularized JAR artifacts (JAR does not contain module descriptor). They help to use 3rd-party libraries inside the modular application. When such artifact is present in the module-path JVM automatically convert it into the automatic module at the run-time.

The automatic modules can read all packages exported by all named modules from specified module path, requires all other modules. They also exports all they packages.

Read Next: Part-3: JPMS/Java Modules - service concept
Main: Java tutorials