Project Jigsaw has had a ripple effect on the entire ecosystem of Java. The enormity of its impact is not due to the complexity involved but the jitters of imbibing something into the bloodstream that were not equipped in its initial design phases. Over a decade, Java has become a reliable platform for many business-critical applications. A structural change with even a minor glitch can be catastrophic. Therefore, the team had to be absolutely sure about its effect on the existing system. The idea of modularizing Java was long overdue since Java 8. Even it had a tint of modularity in JDK (Java Development Kit) releases. Java 9 went through several false alarms and finally got a push on 21st Sept 2017. This article describes the key structural changes brought to JRE (Java Runtime Environment) and JDK due to modularization.
Overview
Apart from leveraging strong encapsulation, one of the primary motivations of the Java Module System is to make it modular to an extent scalable enough to deploy even in the smallest of devices. JRE is the foundation of the Java Platform and JDK provides the necessary means to create a program entity that runs on that environment. The JDK, however, includes JRE. The byte code produced by the Java compiler only makes sense to the virtual machine which is a part of the JRE. The services such as libraries, garbage collection, and so forth, are part of the runtime environment. Until Java 9, both JRE and JDK were a monolithic artefact. As a result, a program that only required a subset of services had no other option but to ship the whole JRE with the program. This is a problem akin to carrying an arsenal when you only need a gun.
The JDK Directory Structure
The overall goal of modularizing JDK and JRE is to leverage performance, maintainability, and security. The JRE is the core platform of Java whereas the JDK includes the JRE along with development tools and libraries. The development tools and libraries aid in creating Java applications that run on JRE. One may install JRE or JDK according to the requirement. The first noticeable change can be seen the directory structure, as arranged by Java 9.
Prior to this version, Java had the following directory structure:
Figure 1: The previous Java directory structure
The JDK directory is the root directory of the JDK software installation. It contains copyright, license, and README files. It also contains src.zip, the archive of source code for the Java platform.
- The JDK/bin directory contained the tools that were run from the command line, such as the javac, javap, jconsole, jar, javadoc, and so on. These tools are used for compiling, debugging, archiving and, other development purposes. Typically, the PATH environment variable contains an entry for this directory.
- The JDK/db directory contains the Java DB database.
- The JDK/include directory contains C-language header files that support native-code programming with the Java Native Interface and the Java Virtual Machine (JVM) Debugger Interface.
- The JDK/jre directory is the root directory of the Java Runtime Environment (JRE) used by the JDK development tools.
- The JDK/jre/bin directory contains executable files for tools and libraries used by the Java platform.
- The JDK/jre/lib directory contains code libraries, property settings, and resource files used by the JRE.
- The JDK/lib directory contained the files that were used by the development tools, such as tools.jar, which contains non-core classes for support of the tools and utilities in the JDK.
- The JDK/man directory contains man pages for the JDK tools.
Ref: JDK and JRE File Structure of Java 8 Documentation.
The new directory structure arranged by Java 9 is shown in Figure 2:
Figure 2: The Java 9 directory structure
Observe that the directory structure of JDK and JRE is almost the same, except that JDK has two additional directories: jmods and include. Also, there is no jre sub directory in JDK9.
- The JDK directory is the root directory of the JDK software installation. This directory also contains copyright, README, and src.zip files, which are the source code archive file of the Java platform.
- The JDK/bin directory contains the executable and command-line launchers that are defined by the modules linked to the image.
- The JDK/conf directory contains the .properties, .policy, and other configuration files intended to be edited by developers, deployers, and end users.
- The JDK/lib directory contains private implementation details of the runtime system. These files are not intended for external use and must not be modified.
- The JDK/jmods directory contains the compiled module definitions.
- The JDK/legal directory contains copyright and license files for each module.
- The JDK/include directory contains C-language header files that support native-code programming with the Java Native Interface and the Java Virtual Machine (JVM) Debugger Interface.
- The JRE is the root directory of the JRE software installation. This directory contains README and other JRE folders.
- The JRE/bin directory contains the executable and command-line launchers that are defined by the modules linked to the image.
- The JRE/conf directory contains the .properties, .policy, and other configuration files intended to be edited by developers, deployers, and end users.
- The JRE/lib directory contains private implementation details of the runtime system. These files are not intended for external use and must not be modified.
- The JRE/legal directory contains copyright and license files for each module.
Ref: Installed Directory Structure of JDK and JRE of Java 9 Documentation.
JDK Modules
The entire JDK has been divided in to a set of modules. As a result, one can nit-pick a set according to the requirement either during compilation, build time, or during run time into a variety of configurations. The module name specific to JDK begins with “jdk”. The list with descriptions is as follows (*).
Module | Description |
jdk.accessibility | Defines JDK utility classes used by implementers of Assistive Technologies. |
jdk.attach | Defines the attach API. |
jdk.charsets | Provides charsets that are not in java.base (mostly double byte and IBM charsets). |
jdk.compiler | Defines the implementation of the system Java compiler and its command line equivalent, javac, as well as javah. |
jdk.crypto.cryptoki | Provides the implementation of the SunPKCS11 security provider. |
jdk.crypto.ec | Provides the implementation of the SunEC security provider. |
jdk.dynalink | Defines the API for dynamic linking of high-level operations on objects. |
jdk.editpad | Provides the implementation of the edit pad service used by jdk.jshell. |
jdk.hotspot.agent | Defines the implementation of the HotSpot Serviceability Agent. |
jdk.httpserver | Defines the JDK-specific HTTP server API. |
jdk.incubator.httpclient | Defines the high-level HTTP and WebSocket API. |
jdk.jartool | Defines tools for manipulating Java Archive (JAR) files, including the jar and jarsigner tools. |
jdk.javadoc | Defines the implementation of the system documentation tool and its command line equivalent, javadoc. |
jdk.jcmd | Defines tools for diagnostics and troubleshooting a JVM, such as the jcmd, jps, and jstat tools. |
jdk.jconsole | Defines the JMX graphical tool, jconsole, for monitoring and managing a running application. |
jdk.jdeps | Defines tools for analysing dependencies in Java libraries and programs, including the jdeps, javap, and jdeprscan tools. |
jdk.jdi | Defines the Java Debug Interface. |
jdk.jdwp.agent | Provides the implementation of the Java Debug Wire Protocol (JDWP) agent. |
jdk.jlink | Defines the jlink tool for creating run-time images, the jmod tool for creating and manipulating JMOD files, and the jimage tool for inspecting the JDK implementation-specific container file for classes and resources. |
jdk.jshell | This module provides support for Java Programming Language ‘snippet’ evaluating tools, such as Read-Eval-Print Loops (REPLs), including the jshell tool. |
jdk.jsobject | Defines the API for the JavaScript Object. |
jdk.jstatd | Defines the jstatd tool for starting a daemon for the jstat tool to monitor JVM statistics remotely. |
jdk.localedata | Provides the locale data for locales other than the US. |
jdk.management | Defines JDK-specific management interfaces for the JVM. |
jdk.management.agent | Defines the JMX management agent. |
jdk.naming.dns | Provides the implementation of the DNS Java Naming provider. |
jdk.naming.rmi | Provides the implementation of the RMI Java Naming provider. |
jdk.net | Defines the JDK-specific Networking API. |
jdk.pack | Defines tools for transforming a JAR file into a compressed pack200 file and transforming a packed file into a JAR file, including the pack200 and unpack200 tools. |
jdk.packager.services | Defines the services used by the Java packager tool. |
jdk.policytool | Defines the GUI tool for managing policy files, called policytool. |
jdk.rmic | Defines the rmic compiler for generating stubs and skeletons using the Java Remote Method Protocol (JRMP) and stubs and tie class files (IIOP protocol) for remote objects. |
jdk.scripting.nashorn | Provides the implementation of Nashorn script engine and the runtime environment for programs written in ECMAScript 5.1. |
jdk.sctp | Defines the JDK-specific API for SCTP. |
jdk.security.auth | Provides implementations of the javax.security.auth.* interfaces and various authentication modules. |
jdk.security.jgss | Defines Java extensions to the GSS-API and an implementation of the SASL GSSAPI mechanism. |
jdk.snmp | Defines the SNMP management agent. |
jdk.xml.dom | Defines the subset of the W3C Document Object Model (DOM) API that is not part of the Java SE API. |
jdk.zipfs | Provides the implementation of the zip file system provider. |
*excerpt from Java 9 API Documentation
Effect of Modular JDK
Modular JDK provides the nifty freedom to combine JDK modules into a variety of configurations, according to the need. The idea is somewhat an augmentation of the concept of compact profiles introduced with Java 8. Custom configuration is particularly advantageous not only in creating scalable Java application but also shipping it in a runtime environment as a scalable platform. The configuration can have a specific set of modules as opposed to the Java platform as a monolithic artefact. This would leverage the performance, maintainability, and security of a Java application. The modular structure also introduced a new URI scheme for naming modules, classes, and resources stored in a runtime image. This strengthens the principle of encapsulation to a whole new level. Most of the JDK’s internal APIs are hidden except a few critical ones, until some supported versions are introduced in future versions.
Conclusion
Java 9 took the idea of modularity from its predecessor to a whole new level. The intricacy of JDK modularity is not going to affect many application developers. However, the internal APIs restructuring is crucial for the developers who deal with core Java SE Platform. To put it in simple terms, the whole Java library—including the Java Platform—has just gone into another level of abstraction and we can program as usual. We can still ride reliably on Java 8 for a while until Java 9 matures enough to carry critical applications effectively.