module java.sql {
requires transitive java.logging
requires transitive java.xml
uses java.sql.Driver
exports java.sql
exports javax.sql
exports javax.transaction.xa
}
Java 9 is scheduled for September 21st
slides at slides.codefx.org
code on GitHub at
CodeFX-org/demo-java-9-migration
JARs have:
no name the JVM cares about
no explicit dependencies
no well-defined API
no concept of versions
Modules are like JARs but have:
proper names
explicit dependencies
a well-defined API
no concept of versions
Important goals:
reliable configuration
strong encapsulation
A file module-info.java
:
module java.sql {
requires transitive java.logging
requires transitive java.xml
uses java.sql.Driver
exports java.sql
exports javax.sql
exports javax.transaction.xa
}
module java.sql {
requires transitive java.logging
requires transitive java.xml
}
Module system enforces:
all required modules are present
no ambiguity
no static dependency cycles
no split packages
module java.sql {
exports java.sql
exports javax.sql
exports javax.transaction.xa
}
Say you want to access java.sql.ResultSet
.
Module system only grants access if:
ResultSet
is public
java.sql
is exported by java.sql
your module reads java.sql
decoupling via services
finer grained dependencies and exports
open packages and modules (for reflection)
unnamed and automatic modules (for migration)
layers (for containers)
jlink
to create runtime images
Modularized JDK and legacy JARs have to cooperate.
Two requirements:
for the module system to work,
everything needs to be a module
for compatibility, the class path
and regular JARs have to keep working
The Unnamed Module
contains all JARs on the class path
(including modular JARs).
has no name (surprise!)
can read all modules
exports all packages
Inside the unnamed module
"the chaos of the class path" lives on.
Internal APIs are encapsulated by default.
What exactly is "internal"?
everything not exported by a module
includes most com.sun.*
packages
includes all sun.*
packages
except parts of sun.misc
Unsafe
and others are available
in jdk.unsupported for a while.
Compilation will fail for internal dependencies:
use --add-exports
to export packages
In Java 9, run time access is allowed
but reflection will result in a warning.
use --add-exports
to export packages
use --add-opens
to open packages
for deep reflection
use --illegal-access
to configure behavior
Java EE modules are not included by default:
java.activation, java.corba, java.transaction
java.xml.bind, java.xml.ws, java.xml.ws.annotation
Have to be added to compiler and JVM
with --add-modules
.
No two modules can contain the same packages
(exported or not).
for named modules this is checked
for the unnamed module it is not
classes in the unnamed package are "invisible"
Two ways to mend the split:
for upgreadable modules, use the JAR instead
of the module (--upgrade-module-path
)
for individual classes, merge the JAR with
the module (--patch-module
)
Class path is for regular JARs,
module path is for modular JARs?
Wrong!
Class path is for the unnamed module,
module path is for named modules!
You can put modular JARs in the class path
and everything works like before.
you can modularize projects,
without clients even realizing
start with the modularization
from the bottom up
What if you want to modularize your code
but your dependencies aren’t yet?
proper modules can not depend on
"the chaos on the class path"
this is not possible:
module monitor.rest {
// we need spark.core
requires unnamed;
}
An Automatic Module
is created for each "regular" JAR
on the module path.
gets a name based on the file name or a
manifest entry AUTOMATIC-MODULE-NAME
can read all modules
(including the Unnamed Module)
exports all packages
put spark-core-2.6.0.jar
on the module path
then this works:
module monitor.rest {
requires spark.core;
}
Class Path | Module Path | |
---|---|---|
Regular JAR | Unnamed Module | Automatic Module |
Modular JAR | Unnamed Module | Named Module |
The module system as a service registry:
module java.sql {
uses java.sql.Driver
}
module mysql.driver {
provides java.sql.Driver
with com.mysql.MySQLDriver;
}
Code in java.sql can now do this:
List<Driver> drivers = new ArrayList<>();
ServiceLoader
.load(Driver.class)
.forEach(drivers::add);
If you want more details:
Java 9 Migration Guide
(tiny.cc/java-9-migration)
If you run into problems:
For the the full picture get my book:
The Java 9 Module System
(tiny.cc/j9ms)
⇜ Get my book!
You can hire me:
training (Java 8/9, JUnit 5)
consulting (Java 8/9)