Example example_unnamed-module-reflection-illegal-access
Part of the full Java 9 Jigsaw modules example suite.
|
Authors
Originally written by Martin Lehmann, Kristine Schaal and RĂ¼diger Grammes (cf. original repository). 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
-
The unnamed module (i.e. the classpath) and "normal" modules modb and modc.
-
modb is accesses from the unnamed module.
-
modc is not really relevant but only needed to allow a class in modb to be exported-to only to modc.
Module Dependency Graph, created with DepVis
Example shows …
The usage of the Java command line option --illegal-access, aka the "kill switch".
See Java9 Maillinglist for details.
Four classes on the classpath, i.e. in the unnamed module, access other classes with reflective access.
-
cpmain/pkgcpmain.MainCallingJavaBaseJDKInternal.javadoes reflective access to a class from modulejava.base, packagejdk.internal(a package which is new in Java9). An explicit--add-opensis hence needed. -
cpmain/pkgcpmain.MainCallingJavaBaseSunNet.javadoes reflective access to a class from modulejava.base, packagesun.net(a package which has existed before, in Java8). The kill-switch--illegal-access=permitwill hence work. -
cpmain/pkgcpmain.MainCallingJavaDesktop.javadoes reflective access to a class from modulejava.desktop, packagesun.awt(a package which has existed before, in Java8). The kill-switch--illegal-access=permitwill hence work. -
cpmain/pkgcpmain.MainCallingJavaBaseModB.javadoes reflective access to a class from modulemodb(a package which has not existed before Java9). An explicit--add-opensis hence needed.
Note that the kill switch only works for classes which had been available before Java9, i.e. were part of Java8. See also explanation here.
|
JDK 17+ Compatibility Changes
The This example originally contained 20 variants demonstrating different combinations of
The remaining variants (1, 5, 10, 15, 16, 20) demonstrate the only two behaviors now available in JDK 17+:
For applications migrating to JDK 17+, replace any |
See the run script run.sh for the remaining variants demonstrating --add-opens usage.
Output
This example uses golden master testing to ensure output consistency.
The expected output is compared with actual output using verify.sh.
Expected Output
Caught exception: class java.lang.reflect.InaccessibleObjectException
jdk.internal.math.DoubleConsts
sun.net.PortConfig
sun.awt.OSInfo
pkgb.BFromModule, id=ID_MainCallingModB_14
Caught exception: class java.lang.reflect.InaccessibleObjectException
pkgb.BFromModule, id=ID_MainCallingModB_14
pkgbinternal.BFromModuleButInternal, id=ID_MainCallingModB_26
pkgbexportedqualified.BFromModuleButExportedQualified, id=ID_MainCallingModB_38
Actual Output
Caught exception: class java.lang.reflect.InaccessibleObjectException
jdk.internal.math.DoubleConsts
sun.net.PortConfig
sun.awt.OSInfo
pkgb.BFromModule, id=ID_MainCallingModB_14
Caught exception: class java.lang.reflect.InaccessibleObjectException
pkgb.BFromModule, id=ID_MainCallingModB_14
pkgbinternal.BFromModuleButInternal, id=ID_MainCallingModB_26
pkgbexportedqualified.BFromModuleButExportedQualified, id=ID_MainCallingModB_38
Maven 4 Output
Caught exception: class java.lang.reflect.InaccessibleObjectException
jdk.internal.math.DoubleConsts
sun.net.PortConfig
sun.awt.OSInfo
pkgb.BFromModule, id=ID_MainCallingModB_14
Caught exception: class java.lang.reflect.InaccessibleObjectException
pkgb.BFromModule, id=ID_MainCallingModB_14
pkgbinternal.BFromModuleButInternal, id=ID_MainCallingModB_26
pkgbexportedqualified.BFromModuleButExportedQualified, id=ID_MainCallingModB_38
Maven 4 Migration
This example required a special migration approach due to the presence of classpath code (unnamed module) that depends on explicit modules.
Standard Migration
The explicit modules (modb, modc) were migrated using the standard Module Source Hierarchy approach with direct paths to the original source directories.
Special Handling: Classpath Code Dependent on Modules
- Problem
-
Maven 4’s Module Source Hierarchy requires module descriptors (module-info.java) for all source entries. This example contains
cpmain, which is classpath code (unnamed module) without module-info.java.Additionally,
cpmainneeds to access classes frommodbduring compilation, requiring the modules to be compiled first. - Solution
-
Hybrid compilation approach in
m4/compile.sh:-
Maven compiles explicit modules (modb, modc) first
-
Package modules as JARs in mlib/
-
Manual javac compilation of cpmain with classpath pointing to mlib/*
The compilation order is critical: modules must be compiled and packaged before cpmain.
-
Runtime uses test variants with
--add-opensflags to demonstrate JDK encapsulation behavior (see JDK 17+ Compatibility Changes note above)
-
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
-
Compilation order matters: cpmain depends on modb during compilation
-
The classpath/module-path split must be maintained at both compile-time and runtime
-
The example demonstrates illegal reflective access behavior and
--add-opensusage