Example example_layer-all-modules-in-boot-layer

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?

Layers in this example

Only the standard boot layer, which has all modules.

Modules in this example

  • modcommon which has standard functionality used by all other modules

  • modauto1 representing a third party library (in version V1)

  • modbar which requires automatic module modauto1

  • modfoo which requires automatic module modauto1

  • modmain which does reflective calls to modbar and modfoo

Module Dependency Graph, created with DepVis

Example’s Module Dependency Graph

Example shows …​

The examples shows what happens, if modmain/pkgmain.Main does reflective calls to classes in module modfoo or modbar, respectively. All takes place in the boot layer, as the output of modcommon/pkgcommon.LayerPrinter shows.

So all modules modmain, modcommon, modfoo, modbar are in the same layer, in the standard boot layer.

As modmain does not require modfoo and modbar, we have to specify --add-modules modbar,modfoo in the run script run.sh.

Output

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

Expected Output

Infos for Layer and Module which contain pkgmain.Main, id=ID_Main_13
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain

Reflective call to pkgfoo.Foo in modfoo in current boot layer...
Infos for Layer and Module which contain pkgfoo.Foo, id=ID_Main_51, using automatic module version V1
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
pkgfoo.Foo, id=ID_Main_51, using automatic module version V1

Reflective call to pkgbar.Bar in modbar in current boot layer...
Infos for Layer and Module which contain pkgbar.Bar, id=ID_Main_51, using automatic module version V1
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
pkgbar.Bar, id=ID_Main_51, using automatic module version V1

Actual Output

Infos for Layer and Module which contain pkgmain.Main, id=ID_Main_13
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain

Reflective call to pkgfoo.Foo in modfoo in current boot layer...
Infos for Layer and Module which contain pkgfoo.Foo, id=ID_Main_51, using automatic module version V1
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
pkgfoo.Foo, id=ID_Main_51, using automatic module version V1

Reflective call to pkgbar.Bar in modbar in current boot layer...
Infos for Layer and Module which contain pkgbar.Bar, id=ID_Main_51, using automatic module version V1
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
pkgbar.Bar, id=ID_Main_51, using automatic module version V1

Maven 4 Output

Infos for Layer and Module which contain pkgmain.Main, id=ID_Main_13
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain

Reflective call to pkgfoo.Foo in modfoo in current boot layer...
Infos for Layer and Module which contain pkgfoo.Foo, id=ID_Main_51, using automatic module version V1
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
pkgfoo.Foo, id=ID_Main_51, using automatic module version V1

Reflective call to pkgbar.Bar in modbar in current boot layer...
Infos for Layer and Module which contain pkgbar.Bar, id=ID_Main_51, using automatic module version V1
Layer (java.lang.ModuleLayer), boot layer
Layer's parents: none, as this is the boot layer
Layer's list of modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
Layer's configuration with its list of resolved modules:
java.base, java.compiler, java.datatransfer, java.desktop, java.logging, java.management, java.management.rmi, java.naming, java.prefs, java.rmi, java.security.jgss, java.security.sasl, java.smartcardio, java.xml, java.xml.crypto, jdk.charsets, jdk.compiler, jdk.crypto.cryptoki, jdk.crypto.ec, jdk.internal.opt, jdk.jartool, jdk.javadoc, jdk.jdeps, jdk.jfr, jdk.jlink, jdk.localedata, jdk.management, jdk.management.jfr, jdk.naming.dns, jdk.naming.rmi, jdk.security.auth, jdk.security.jgss, jdk.unsupported.desktop, jdk.zipfs, modauto1, modbar, modcommon, modfoo, modmain
pkgbar.Bar, id=ID_Main_51, using automatic module version V1

Maven 4 Migration

This example required a special migration approach due to mixing explicit modules with automatic modules.

Standard Migration

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

Special Handling: Automatic Modules

This example demonstrates automatic modules (modauto1) which lack module descriptors.

Problem

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

Solution

Hybrid compilation approach in m4/compile.sh:

  1. Manual javac invocation compiles modauto1 to amlib1/modauto1.jar:

    javac -d classes/modauto1 --release 11 $(find ../src/modauto1 -name "*.java")
    jar --create --file=amlib1/modauto1.jar -C classes/modauto1 .
  2. Maven compiles the explicit modules (modbar, modcommon, modfoo, modmain) with compiler arguments:

    <compilerArgs>
      <arg>--module-path</arg>
      <arg>${project.basedir}/amlib1</arg>
    </compilerArgs>
  3. Runtime uses both paths:

    java --module-path mlib${PATH_SEPARATOR}amlib1 \
         --add-modules modbar,modfoo \
         --module modmain/pkgmain.Main .

This hybrid approach is necessary because:

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

  • Automatic modules must be compiled as non-modular JARs (without module-info.java)

  • The --module-path compiler argument allows explicit modules to find the automatic module

  • Separating amlib1/ from mlib/ maintains the automatic module/explicit module distinction