![]() | |
|
Unnamed module
From Java 9 and forward, all Java classes must be located in a module for the Java VM to use them. But in Java 9 (and Java 11 too) you can still use the -classpath
(synonyms:
-cp
and --class-path
) argument to the Java VM when running an application. On the classpath you can include all your older Java classes, just like you have
done before Java 9. All classes found on the classpath will be included in what Java calls the unnamed module.
The unnamed module exports
all its packages. However, the classes in the unnamed module are only readable by other classes in the unnamed module. No named module can read the
classes of the unnamed module.
If a package is exported by a named module, but also found in the unnamed module, the package from the named module will be used.
The unnamed module opens
all its packages. However, the classes in the unnamed module are only accessible via Reflection API by other classes in the unnamed module.
No named module can access via Reflection API the classes of the unnamed module.
All classes in the unnamed module requires
all modules found on the module path. All classes in the unnamed module can read all classes exported by all
the Java modules found on the module path.
Let's check scenario when named module code depends on unnamed module code. Create non-modular greeter.jar
with the p1.Greeter
class:
package p1; public class Greeter { public static void greet() { System.out.println("Greeting from Java 8 !"); } }
C:\1Z0-817\LIB │ └───p1 Greeter.java
C:\1Z0-817\lib>javac p1/Greeter.java
C:\1Z0-817\lib>jar cvf greeter.jar p1 added manifest adding: p1/(in = 0) (out= 0)(stored 0%) adding: p1/Greeter.class(in = 409) (out= 288)(deflated 29%) adding: p1/Greeter.java(in = 138) (out= 113)(deflated 18%)
Now create named module for client:
package p2; import p1.Greeter; public class Client { public static void main(String[] args) { Greeter.greet(); } }
with module definition:
module MOD { }
C:\1Z0-817\MOD3 │ module-info.java │ └───p2 Client.java
Try to compile:
C:\1Z0-817\mod3>javac -cp ../lib/greeter.jar module-info.java p2/Client.java p2\Client.java:3: error: package p1 is not visible import p1.Greeter; ^ (package p1 is declared in the unnamed module, but module p1 does not read it) 1 error
As you can see, named module MOD
cannot access at compile (and runtime) time class from unnamed module added via -cp
option.
Now, try the opposite scenario: accessing named module (Greeter
) from unnamed module (Client
).
Create modular JAR first:
package p1; public class Greeter { public static void greet() { System.out.println("Greeting from Java 9 !"); } }
module-info.java
:
module MOD { exports p1; }
C:\1Z0-817\mod4>javac module-info.java p1/Greeter.java
C:\1Z0-817\MOD4 │ module-info.class │ module-info.java │ └───p1 Greeter.class Greeter.java
Create a modular JAR:
C:\1Z0-817>jar --create --file greeter.jar -C mod4 .
C:\1Z0-817>jar -tvf greeter.jar 0 Fri Mar 29 23:16:54 AST 2019 META-INF/ 66 Fri Mar 29 23:16:54 AST 2019 META-INF/MANIFEST.MF 186 Fri Mar 29 23:16:54 AST 2019 module-info.class 14 Fri Mar 29 23:13:04 AST 2019 module-info.java 0 Fri Mar 29 23:14:20 AST 2019 p1/ 409 Fri Mar 29 23:14:20 AST 2019 p1/Greeter.class 138 Fri Mar 29 23:13:20 AST 2019 p1/Greeter.java
Now, create unnamed client module:
package p2; import p1.Greeter; public class Client { public static void main(String[] args) { Greeter.greet(); } }
C:\1Z0-817\LIB1 └───p2 Client.java
Compile:
C:\1Z0-817>javac -cp greeter.jar lib1/p2/Client.java
Create non-modular executable JAR file:
jar --create --file client.jar --main-class p2.Client -C lib1 .
C:\1Z0-817>jar -tvf client.jar 0 Fri Mar 29 23:30:54 AST 2019 META-INF/ 89 Fri Mar 29 23:30:54 AST 2019 META-INF/MANIFEST.MF 0 Fri Mar 29 23:30:24 AST 2019 p2/ 301 Fri Mar 29 23:30:24 AST 2019 p2/Client.class 140 Fri Mar 29 22:48:34 AST 2019 p2/Client.java
Run the client:
C:\1Z0-817>java -p greeter.jar --add-modules MOD -jar client.jar Greeting from Java 9 !
This demonstrated unnamed module access to named module.
![]() | |
When you are trying to launch an application from a non-modular JAR so you have to explicitly resolve required
modules by
The required named modules have to be on module graph, e.g. add by |
Automatic modules
Automatic modules are named modules which are automatically created from a non-modular JARs. It happens when the JAR is placed on the module path
(as dependency) of a modular application via --module-path
or -p
options.
![]() | |
A JAR file that does not have a |
A non-modular JAR becomes modular (automatic module) JAR when used by a modular application via --module-path
option (and becomes part of the unnamed module when
used by a modular application via --class-path
option).
![]() | |
Automatic module
Automatic module |
Let's create non-modular JAR:
package p1; public class Greeter { public static void greet() { System.out.println("Greeting from automatic module !"); } }
C:\1Z0-817\LIB2 └───p1 Greeter.java
Compile:
C:\1Z0-817\lib2>javac p1/Greeter.java
Create JAR:
C:\1Z0-817>jar --create --file greeter-lib.jar -C lib2 .
![]() | |
|
Get description of the new automatic module:
C:\1Z0-817>jar --file greeter-lib.jar --describe-module No module descriptor found. Derived automatic module. greeter.lib automatic requires java.base mandated contains p1
Create new module application in mod5
directory:
package p2; import p1.Greeter; public class Client { public static void main(String[] args) { Greeter.greet(); } }
As you saw above, the automatic module name will be greeter.lib
and client application requires
it:
module MOD { requires greeter.lib; }
Compile:
C:\1Z0-817>javac -p greeter-lib.jar mod5/module-info.java mod5/p2/Client.java
C:\1Z0-817\MOD5 │ module-info.class │ module-info.java │ └───p2 Client.class Client.java
Run:
C:\1Z0-817>java -p greeter-lib.jar;mod5 -m MOD/p2.Client Greeting from automatic module !
Optionally create module JAR and check dependencies:
C:\1Z0-817>jar --create --file client-mod.jar -C mod5 .
C:\1Z0-817>jar --file client-mod.jar --describe-module MOD jar:file:///C:/1Z0-817/client-mod.jar/!module-info.class requires greeter.lib requires java.base mandated contains p2
Optionally check dependencies of the modular client:
C:\1Z0-817>jdeps --module-path client-mod.jar;greeter-lib.jar -s --module MOD MOD -> greeter.lib MOD -> java.base
Automatic module name derivation
If the JAR file has the attribute "Automatic-Module-Name
" in its main manifest (META-INF/MANIFEST.MF
) then its value is the module
name. The module name is otherwise derived from the name of the JAR file.
The version, and the module name when the attribute "Automatic-Module-Name
" is not present, are derived from the file name of the JAR file as follows:
The ".jar
" suffix is removed.
If the name matches the regular expression "-(\\d+(\\.|$))
" then the module name will be derived from the subsequence
preceding the hyphen of the first occurrence. The subsequence after the hyphen is parsed as a Version
and ignored if it
cannot be parsed as a Version
.
All non-alphanumeric characters ([^A-Za-z0-9]
) in the module name are replaced with a dot ("."), all repeating dots are
replaced with one dot, and all leading and trailing dots are removed.
As an example, a JAR file named "foo-bar.jar
" will derive a module name "foo.bar
" and no version. A JAR file named
"foo-bar-1.2.3-SNAPSHOT.jar
" will derive a module name "foo.bar
" and "1.2.3-SNAPSHOT
" as the version
The set of packages in the module is derived from the non-directory entries in the JAR file that have names ending in ".class
". A candidate
package name is derived from the name using the characters up to, but not including, the last forward slash. All remaining forward slashes are replaced
with dot ("."). If the resulting string is a legal package name then it is assumed to be a package name. For example, if the JAR file contains
the entry "p/q/Foo.class
" then the package name derived is "p.q
".
The contents of entries starting with META-INF/services/
are assumed to be service configuration files. If the name of a file (that follows
META-INF/services/
) is a legal class name then it is assumed to be the fully-qualified class name of a service type. The entries in
the file are assumed to be the fully-qualified class names of provider classes.
If the JAR file has a Main-Class
attribute in its main manifest, its value is a legal class name, and its package is in the set of
packages derived for the module, then the value is the module main class.
Java command line options for modules
--module-path
(-p
)
Specifies the module path. We need to provide one or more directories that will contain modules. Also can contain JAR files.
java -p greeter-lib.jar;mod5 -m MOD/p2.Client
--module-source-path
Specify where to find input source files for multiple modules.
Assume src
directory contains several modules directories:
C:\1Z0-817\SRC ├───modA │ module-info.class │ └───modB module-info.class
Then you can use:
javac --module-source-path src ...
--describe-module
(-d
)
Describe the module:
java --describe-module java.base java.base@11.0.2 exports java.io exports java.lang ...
or describe module contained in JAR:
C:\1Z0-817>jar --describe-module --file=client-mod.jar MOD jar:file:///C:/1Z0-817/client-mod.jar/!module-info.class requires greeter.lib requires java.base mandated contains p2
--add-modules
Adds the specified modules to the default set of modules.
jlink --module-path modA;modB --add-modules MOD --output greeterapp
--list-modules
List all observable modules in Java
java --list-modules
--module <module_name>
(-m
) for javac
compiler command
Compile only the specified module, check timestamps
--module <module>[/<mainclass>]
(-m
) for java
interpreter command
Executes the main class in a module:
java -p service.jar;provider.jar;service-client -m modC/app.Client
![]() | |
|
![]() ![]() ![]() |