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 is 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) with reflective access:

  • Reflective access from a module to the classpath works, as reflection has implicit readability (no --add-reads modmain=ALL-UNNAMED necessary)

  • 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 "covered" ("hidden") by code in modb! This is also the case for reflective access.

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

Main: from pkgboncp.BFromClasspath (in cpb)
ClassNotFoundException: pkgb.BFromClasspath can't be found, as it is hidden by pkgb in modb!
Main: from pkgb.B (in modb)

Actual Output

Main: from pkgboncp.BFromClasspath (in cpb)
ClassNotFoundException: pkgb.BFromClasspath can't be found, as it is hidden by pkgb in modb!
Main: from pkgb.B (in modb)

Maven 4 Output

Main: from pkgboncp.BFromClasspath (in cpb)
ClassNotFoundException: pkgb.BFromClasspath can't be found, as it is hidden by pkgb in modb!
Main: from pkgb.B (in modb)

Maven 4 Migration

This example required a special migration approach due to the presence of classpath code (unnamed module).

Standard Migration

The explicit modules (modb, modmain) were migrated using the standard Module Source Hierarchy approach with direct paths to the original source directories.

Special Handling: Classpath Code with Reflective Access

Problem

Maven 4’s Module Source Hierarchy requires module descriptors (module-info.java) for all source entries. This example contains cpb, which is classpath code (unnamed module) without module-info.java.

Additionally, modmain uses reflection to access classes in the unnamed module, which requires --add-reads modmain=ALL-UNNAMED.

Solution

Hybrid compilation approach in m4/compile.sh:

  1. Manual javac compilation of cpb to cplib/cpb.jar

  2. Maven compiles explicit modules (modb, modmain) with compiler arguments:

    • --add-reads modmain=ALL-UNNAMED - allows modmain to reflectively access unnamed module

    • --class-path cplib/cpb.jar - makes cpb available on classpath during compilation

  3. Runtime uses --module-path mlib for modules and --class-path cplib/cpb.jar for classpath code

This hybrid approach is necessary because:

  • Maven 4’s Module Source Hierarchy cannot compile code without module-info.java

  • Classpath code (unnamed module) must be compiled separately from explicit modules

  • Reflective access from explicit modules to the unnamed module requires --add-reads

  • The classpath/module-path split must be maintained at both compile-time and runtime