Example example_unnamed-module_access-from-explicit-module

Part of the full Java 9 Jigsaw modules example suite.

Authors

Migrated for Java Modules support documentation of Apache MavenTM in the course of the Maven Support & Care program by Gerd Aschemann (and other team members) as forked repository. Please add discussions, requirements, bugfixes, etc. to the fork instead of the original.

What is this example about?

Modules in this example

  • modb, modmain, and also classes for the unnamed module (cpb)

  • modmain contains a Main class which are started in run.sh

Module Dependency Graph, created with DepVis

Example’s Module Dependency Graph

Example shows …​

The examples illustrates the accessibility rules access to the classpath (i.e. from an explicit module on the module-path to the unnamed module):

  • Normally explicit modules cannot access code on the classpath.

  • The Main class in modmain can access classes in the unnamed module only, if an compile and run option --add-reads modmain=ALL-UNNAMED is set explicitely.

  • Note also that the Main class in modmain cannot access any package on the classpath if an explicit module like modb has such a package exported. This is here the case for pkgb. The module modmain cannot access the class pkgb.BFromClasspath because it is somewhat "covered" ("hidden") by code in modb!

The script run.sh starts the main class from modmain.

Output

This example uses golden master testing to ensure output consistency. The expected output is compared with actual output using verify.sh.

Expected Output

from pkgboncp.BFromClasspath (in cpb)
from pkgb.B (in modb)
from pkgb.BFromModule (in modb)

Actual Output

from pkgboncp.BFromClasspath (in cpb)
from pkgb.B (in modb)
from pkgb.BFromModule (in modb)

Maven 4 Output

from pkgboncp.BFromClasspath (in cpb)
from pkgb.B (in modb)
from pkgb.BFromModule (in modb)

Maven 4 Migration

This example required a special migration approach due to mixing modular code with classpath code (unnamed module).

Standard Migration

The modules (modb, modmain) were migrated using the standard Module Source Hierarchy approach documented in the central Maven 4 Migration guide.

Special Handling: Classpath Code

This example demonstrates explicit modules accessing the unnamed module (classpath) via --add-reads modmain=ALL-UNNAMED.

Problem

Maven 4’s Module Source Hierarchy requires module descriptors (module-info.java) for all source entries. The cpb package is classpath code without a module-info.java and cannot be included in the <sources> element.

Solution

Hybrid compilation approach in m4/compile.sh:

  1. Manual javac invocation compiles cpb to cplib/cpb.jar:

    javac -d classes --release 11 $(find ../src/cpb -name "*.java")
    jar --create --file=cplib/cpb.jar -C classes .
  2. Maven compiles the modules (modb, modmain) with compiler arguments:

    <compilerArgs>
      <arg>--add-reads</arg>
      <arg>modmain=ALL-UNNAMED</arg>
      <arg>--class-path</arg>
      <arg>${project.basedir}/cplib/cpb.jar</arg>
    </compilerArgs>
  3. Runtime uses separate paths:

    java --module-path mlib \
         --class-path cplib/cpb.jar \
         --module modmain/pkgmain.Main

This hybrid approach is necessary because:

  • Maven 4’s Module Source Hierarchy is designed for modular code only

  • Classpath code (unnamed module) must be compiled separately and placed on the classpath

  • The --add-reads modmain=ALL-UNNAMED flag allows the explicit module to read the unnamed module

  • Separating cplib/ from mlib/ maintains the classpath/module-path distinction