Class path can get in trouble when multiple classpath elements contain the same package
Class path is searched (linearly) every time a new class is requested
Module Path
Modules form a partition of packages
no package can be in more than one runtime module
Modules perform a directed search
Once the runtime finds a module,it remembers its packages
Never has to search for those packages again
Class loading becomes O(1), not O(n)
So now instead Dependency List as with Classpath, we have a Module Dependency Graph which is Directed Graph on Dependencies.
Following is the Dependency Graph for java.se module which is the Entire JVM Utilities available out of the box.
Breaking a single rt.jar into modules which can be defined in the graph shown above was the reason why Java 9 release took longer than other Java releases. It must have been very difficult task for the Engineering team and hats off to them.
So what about Backward Compatibility??
All Old Codes which are not modularized (available in Classpath) will be put into a one big module called the "Unnamed Module". That module will by default
Requires every other module
Exports / opens every package available in that module
Maximum compatibility with classpath behavior
This sort of behavior allows Java code to incrementally modularized when and if required.
Modules enforce Strong Encapsulation as we discussed in the previous post. Now a Package is not public by default to all other modules unless it is explicitly exported in the module-info.java Module Descriptor.
Can Class D from Module A access Class F from Module B?
With the Module Descriptors mentioned below, yes it is possible as Module A has mentioned as it requires Module B and Module B has exports package Z.
Strong Encapsulation
Module must require other Modules to be used in them.
Module exports packages to specific Modules or to all.
Module opens packages explicitly for reflection.
Accessibility is enforced by compiler, JVM and Reflection.
But why Modules again?
Remember packages starting with sun.* or com.* that were available in rt.jar (JVM Runtime) which were only specific for certain JVM Vendor Implementations and not all. Java programmers have been constantly warned not to use these packages as they will break Platform Independence. But up until Java 9 Modules there was no way to completely stop developers from using those packages.
Enter java.base Module
Following is the Module Descriptor for java.base module. With this as you can see only certain packages are exported and com.*/sun.* packages are only available within the module.
// module-info.java
module java.base {
exports java.lang;
exports java.io;
exports java.net;
exports java.util;
}
Every Module in Java 9 implicitly will have require to java.base. Just like every class in Java will automatically import java.lang.*.
So what does this means?
This means that now there can be a Java Application which is 100% modular with all Jar files being modules. Which means we can't use classpath in those scenarios.
Enter Module Path
Path containing directories which contain modules
Modules can be exploded directories, or modular JARs (other forms too)
The runtime searches the module path when looking for a module.
Plus a Java Application can be an hybrid of Modular as well as Backward Compatible Application in those cases there will be both a Module Path and Class Path.
There is much so talk and hype about Java 9 and its features. There are so many posts about Java 9 and specially on Java 9 Jigshaw or Modules. As a Java Developer for almost a decade now, I was really cautious and concerned about the new features of Java 9 and wanted to learn about it in depth. What better way than learning from the creators of Java 9 itself. Recently I got the chance to view an InfoQ video on a Presentation done byKaren Kinnear who is the Technical Lead for the Hotspot Java Virtual Machine Runtime team at Oracle. This lead me to realize Java 9 is far beyond Modules and the in depth nature of the Modules and the necessity for such time and resource consuming change in the Java Language Framework and Java Virtual Machine.
To start off if we look at all the features available in Java 9, we can list the followings; 102: Process API Updates 110: HTTP 2 Client 143: Improve Contended Locking 158: Unified JVM Logging 165: Compiler Control 193: Variable Handles 197: Segmented Code Cache 199: Smart Java Compilation, Phase Two 200: The Modular JDK 201: Modular Source Code 211: Elide Deprecation Warnings on Import Statements 212: Resolve Lint and Doclint Warnings 213: Milling Project Coin 214: Remove GC Combinations Deprecated in JDK 8 215: Tiered Attribution for javac 216: Process Import Statements Correctly 217: Annotations Pipeline 2.0 219: Datagram Transport Layer Security (DTLS) 220: Modular Run-Time Images 221: Simplified Doclet API 222: jshell: The Java Shell (Read-Eval-Print Loop) 223: New Version-String Scheme 224: HTML5 Javadoc 225: Javadoc Search 226: UTF-8 Property Files 227: Unicode 7.0 228: Add More Diagnostic Commands 229: Create PKCS12 Keystores by Default 231: Remove Launch-Time JRE Version Selection 232: Improve Secure Application Performance 233: Generate Run-Time Compiler Tests Automatically 235: Test Class-File Attributes Generated by javac 236: Parser API for Nashorn 237: Linux/AArch64 Port 238: Multi-Release JAR Files 240: Remove the JVM TI hprof Agent 241: Remove the jhat Tool 243: Java-Level JVM Compiler Interface 244: TLS Application-Layer Protocol Negotiation Extension 245: Validate JVM Command-Line Flag Arguments 246: Leverage CPU Instructions for GHASH and RSA 247: Compile for Older Platform Versions 248: Make G1 the Default Garbage Collector 249: OCSP Stapling for TLS 250: Store Interned Strings in CDS Archives 251: Multi-Resolution Images 252: Use CLDR Locale Data by Default 253: Prepare JavaFX UI Controls & CSS APIs for Modularization 254: Compact Strings 255: Merge Selected Xerces 2.11.0 Updates into JAXP 256: BeanInfo Annotations 257: Update JavaFX/Media to Newer Version of GStreamer 258: HarfBuzz Font-Layout Engine 259: Stack-Walking API 260: Encapsulate Most Internal APIs 261: Module System 262: TIFF Image I/O 263: HiDPI Graphics on Windows and Linux 264: Platform Logging API and Service 265: Marlin Graphics Renderer 266: More Concurrency Updates 267: Unicode 8.0 268: XML Catalogs 269: Convenience Factory Methods for Collections 270: Reserved Stack Areas for Critical Sections 271: Unified GC Logging 272: Platform-Specific Desktop Features 273: DRBG-Based SecureRandom Implementations 274: Enhanced Method Handles
Modular JDK feature is just a small part of it but is a significant one, in this part I am planning to talk about it in depth with some coding examples;
The Why of Modular JDK?
The main reason for a Modular JDK was to avoid Classpath Hell. People who have experience Deploying Java Applications in Production or Pre Production Environments would agree that creating and maintaining the Classpath for a Java Application with the focus to enable future maintenance is a Nightmare and can become a Hell very soon if not done properly.
OSGi Framework tried to address this by creating an Engine in which Classloader Isolated Bundles can run with Strict Contracts to Export and Import Dependency. This was a good approach to solve Classpath hell but the problem was an OSGi Bundle is a Jar on Steroids (Had to have a META-INF/MANIFEST.MF Bundle Descriptor). So Normal Jar Files had to be converted to a OSGi Bundle before those can be used inside an OSGi Engine. Making OSGi Bundles of already existing millions of Jars and maintaining them through latest versions in its entirety could be classified as Hell. So OSGi didn't catch up to its fullest potential.
Plus JVM Classpath scanning was Sequential where when a Class is requested by an Application running in JVM it will scan the Classpath Jars one after the other until it finds the requested Class. This is an O(n) problem which needed to be addressed to improve performance.
The Official Java Team had to come up with something off the shelf. This is the reason Why Modular JDK was created with all the difficulties.
The How of the Modular JDK?
Up until Java 8, there were only 2 concepts of code containers;
1. Package (Public to all)
2. Class inside Package (default or package private, Public to all)
From Java 9 there are 3 concepts of code containers;
1. Module (A module is group of packages with a Module Descriptor)
2. Package inside Module (Public to All modules which can access the module contain the package)
3. Class inside Package (Public within module, Public to certain modules, Public to all modules)
How to create a Module in Java 9?
A module is a same old Java Jar file with a Module Descriptor. A Module Descriptor is a Java Source file with the name module-info.java residing in the root of the source directory.
The Structure of the Module Descriptor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters