Java's much-awaited "Project Jigsaw" is finally here! Java 9 will include a built-in modularity framework, and The Java Module System is your guide to discovering it.
Save 42% off The Java Module System with code slparlog at: https://www.manning.com/books/the-java-9-module-system
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
The Java Module System: reliably configuring Java 9 modules
1. Save 42% off The Java Module
System by Nicolai Parlog with code
slparlog at manning.com
2. Connecting the pieces
Modules are the atomic building blocks, the nodes in
our graph of interacting artifacts. But there can be no
graph without edges connecting the nodes! So the
modules express which other modules they depend on,
creating edges between them.
The next slide shows a graphic of the types of JVM
modules:
Need some background info on Java 9 modules? Check
out the author’s website:
http://blog.codefx.org/tag/jpms/
4. Let’s imagine that we have a module customer and a
module bar.
When a module customer requires module bar in its
declaration, then at run time customer will read bar or,
conversely, bar will be readable by customer.
barcustomer
1. requires bar
2. reads
5. With that in mind, you can see how phrases like
"customer requires bar" and "customer depend on bar“
mirror a static, compile-time relationship between
customer and bar; readability is the more dynamic,
run-time counterpart.
You might be asking: Why is it more dynamic?
While the requires clause is the primal originator of
readability edges, it is by no means the only one – both
command line arguments and the reflection API can be
used to add more.
However they came to be, readability edges are the basis
for reliable configuration and strong encapsulation.
6. Achieving reliable configuration
Reliable configuration aims to ensure that the particular
configuration of artifacts a Java program is compiled
against, or launched with, can sustain the program
without spurious run-time errors.
To this end it performs a couple of checks – which
happen during module resolution.
The next slide shows the verification sequence.
7. 1. First and foremost, the module system checks whether the universe of
observable modules contains all required dependencies (both direct and
transitive) and reports an error if something is missing.
2. There must be no ambiguity, which means that no two artifacts can claim
that they are the same module. This is particularly interesting in the case
where two versions of the same module are present—unfortunately the
module system has no concept of versions and thus treats this as a
duplicate module. Accordingly, you get an error if it runs into this
situation.
3. There must be no static dependency cycles between modules. At run time it
is possible and even necessary for modules to access each other, but these
must not be compile dependencies.
4. Packages should have a unique origin so no two modules contain types in
the same package. If they do, this is called a split package and the module
system will refuse to compile or launch such configurations.
8. This verification is, of course, not airtight and it is still
possible for problems to hide long enough to crash a
running application. If, for example, the wrong version
of a module ends up in the right place, then the
application will still launch (all required modules are
present after all) but crash later when, for example, a
class or method is missing.
The module system is developed to exhibit consistent
behavior across compile and run time, though, so these
errors can be further minimized if it can be guaranteed
that compilation and launch are based on the same
artifacts (for example, a compilation against a module
with the wrong version would fail).
9. Unreliable configurations
Now that you know how the module system is supposed
to work (and when it won’t), let’s see if we can break
things – so you know what to do when things go wrong
(they will).
Imagine that we have a simple monitor application, and
consider monitor.observer.alpha and its declaration:
module monitor.observer.alpha {
requires monitor.observer;
exports monitor.observer.alpha;
}
10. Missing dependencies
Now let’s see what it would look like to try to compile it
with monitor.observer missing:
Missing dependency, no compilation!
monitor.observer.alpha/src/main/java/module-info:2:
error: module not found: monitor.observer
requires monitor.observer
^
1 error
11. A different error would get thrown if the module was
present at compile time, but got lost on the way to the
launch pad. In this instance, the JVM will quit with the
following:
Missing dependencies
Error occurred during initialization of VM
java.lang.module.ResolutionException:
Module monitor.observer not found,
required by monitor.observer.alpha
12. Duplicate modules
Since modules reference one another by name, any
situation where two modules claim to have the same
name is ambiguous. Which one is the correct one to
pick is highly dependent on the context and not
something the module system can generally decide.
So, instead of making a potentially bad decision, it
makes none at all and instead produces an error.
This commitment to failing fast allows the developer to
notice a problem and fix it before it causes any more
problems.
13. Duplicate modules
This is the compile error the module system produces
when trying to compile a module with two variants of
monitor.observer.beta on the module path:
The compiler cannot link the error to one of the files
under compilation because they are not the reason for
the problem. In this case, the artifacts on the module
path are causing the error.
error: duplicate module on application module path
module in monitor.observer.beta
1 error
14. Duplicate modules
In the event of an error going undetected until the JVM
is launched, we get a more precise message that lists
the JAR file names as well:
As we mentioned before, the module system has no
concept of versions – many errors can be traced to
having several versions of the same module on the
module path.
Error occurred during initialization of VM
java.lang.module.ResolutionException:
Two versions of module monitor.observer.beta found in mods
(monitor.observer.beta.jar and monitor.observer.gamma.jar)
15. Dependency cycles
Getting dependency cycles through the compiler takes
some doing, and, if not done properly, will result in a
compile error.
This is how it looks if monitor.persistence and
monitor.statistics depend on each other:
monitor.statistics/src/main/java/module-info:3:
error: cyclic dependence involving monitor.persistence
requires monitor.persistence;
^
1 error
16. Split packages
A split package occurs when two modules contain types
in the same package. For example, the monitor.statistics
module contains a class Statistician in the
monitor.statistics package.
Now let’s assume the monitor module contained a very
simple fallback implementation SimpleStatistician,
and to promote uniformity, the monitor module has
placed it in its own monitor.statistics package.
The error we would get at compile time is on the next
slide:
17. Split packages
Interestingly enough, the compiler only shows an error if
the module under compilation can access the split
package in the other module, which means the split
package must be exported.
monitor/src/main/java/monitor/statistics/SimpleStatistician.java:1:
error: package exists in another module: monitor.statistics
package monitor.statistics;
^
1 error
18. Split packages
Let’s see this another way: SimpleStatistician is
gone and this time monitor.statistics creates the split
module. It gets a Utils class in the monitor package,
and continues to only export the monitor.statistics
package. Compiling monitor.statistics is error-free, which
makes sense because it does not require monitor.
Compiling monitor is more interesting because it
depends on monitor.statistics and both contain types in
the package monitor. But because monitor.statistics
does not export the split package, compilation is
successful.
19. Split packages
That didn’t go so well… Indeed, the module system
checks for split packages on launch and here it doesn’t
matter whether they are exported or not: There can be
no two modules that contain types in the same package.
Error occurred during initialization of boot layer
java.lang.reflect.LayerInstantiationException:
Package monitor in both module monitor.statistics and module monitor
Let’s see what happens when we launch:
20. Grab your copy of The Java Module System and save
42% with code slparlog at manning.com.
Also see: