Modularity in Java 9

One of the distinctive features of any good software engineering practice is modularity. Before Java 9, the developers had to themselves take care of modularity with the limited tool set. One of the key features of Java 9 is modularity and it is going to be a game changer in how we develop software. Modular programming is essentially a way of implementing a program as number of individual components with their distinct functionality. These individual components are known as modules. The central idea is to avoid monolithic design and break a complex system into manageable parts.

Challenges till Java 8

A thought often comes that may be idea of modularity is over-hyped. Do we really need modularity in Java? Before going into the details of various kinds of issues faced due to lack of modularity, does “JAR Hell” ring a bell. The arbitrary complex JAR loading mechanisms lead to a situation which is described as classpath hell or JAR hell. There are a lot of configurations which can lead to this situation. The challenges with Java 8 or earlier systems are as following:

  • Many a times classes and interfaces contained in a JAR file overlap with other classes in some other package to function appropriately. This creates dependency among classes and interfaces. As a result, one JAR file may be dependent on another to execute. Java runtime simply loads the JARs in the order in which they appear in the classpath irrespective of the fact that a copy of the same class may exist in multiple JARs.
  • There are instances where some classes or interfaces remain missing. This is only found during execution. Most of the times, this causes the application to crash giving a runtime error message.
  • A very common and frustrating problem is version mismatch. A JAR file dependent on another JAR file may not work because one or more of its dependent modules may have been upgraded or downgraded to make it compatible.
  • The large size of JDK makes it tough to scale down to small devices. Although Java 8 introduced three different types of profiles – compact1, compact2 and compact3, still the problem could not be resolved. Moreover, the large size of JRE makes it cumbersome to test and maintain applications.
  • Lack of strong encapsulation Java ecosystem as “public” access modifier is too open. Anyone can access it. Even internal APIs can be accessed

The characteristics of a modular system are as following:

  • Module Id and Version – Consistent and unique identity
  • Loose Coupling – Autonomous unit of deployment
  • Communication Contract – Open and Understandable interface
  • Encapsulation – Hidden implementation details

Java 9 Modular System

There is an argument, with some merit, that Java 8 and earlier releases were also modular in some sense. The object-oriented nature of Java ensures basic modularity but has limitations like no versioning of interfaces, non-uniqueness of class at deployment level and no strict compliance of loose coupling. A level of abstraction is added to Java programming environment by use of packages. The key benefit of packages is unique coding namespaces and configuration contexts. But these package conventions are conveniently bypassed, very often leading to an environment of dangerous compile-time couplings. JARs are a good attempt at modularization but they don’t fulfill all the requirements for a truly modular environment.

Java 9 has modular components and segments throughout the entire JDK. The key features supporting modularization are:

  • Modular Source Code – The JRE and JDK are organized into interoperable modules which enables the creation of scalable runtimes that can be executed on small devices.
  • Segmented Code Cache – The new code cache makes intelligent decisions to compile frequently accessed code segments to native code and store them for optimized lookup and future execution. The heap is segmented into 3 distinct units:
    • Non-method code that will be stored permanently in the cache
    • Code that has a potentially long lifecycle (non-profiled code)
    • Transient code (profiled code)
  • Deployment facilities – Tools are provided to support module boundaries, constraints, and dependencies at deployment time

Module Types

The different types of modules are listed below with their descriptions:

  • Application Modules – Modules that are created to achieve functionality. All third-party dependencies lie in this category.
  • Automated Modules – Those JARs which are placed in the module path without module descriptor are known as automated modules. They do an implicit export of all packages and read all other modules. The main benefit of these modules is to use pre-Java 9 build JARs.
  • Unnamed Modules – Any JAR or class on the class path will be in the unnamed module. Since, it does not have any name it can read and export all the modules.
  • Platform Modules – The JDK has also been transformed into a modular structure. These modules are known as platform modules. For e.g.,,

Declaring a Jar file as a module

In order to declare a jar file as a named module, one needs to provide a module-info.class file which is obtained after compiling file. The role of this file is to declare dependencies within the module system and allows the compiler and the runtime to govern the boundaries/access violations between then modules. Some of the module descriptors are described below:

  • module – declares a module called
  • requires – specifies that our module depends on the module, allows this module to access public types exported in the target module.
  • requires transitive – any modules that depend on this module automatically depend on
  • exports says that our module exports public members in package for every module requiring this one.
  • exports to the same as above, but limits which modules can use the public members from the package
  • uses makes the current module a consumer for service
  • provides with registers class a service that provides an implementation of the service.
  • opens allows other modules to use reflection to access the private members of package
  • opens to does the same, but limits which modules can have reflection access to the private members in the

All the popular IDEs support the syntax.


Prior to Java 9, JAR files were the closest one could get to modules. There were pain points like “JAR hell” which made the development process quite frustrating. Java 9 has tried to address it primarily through project Jigsaw. Both JRE and JDK have been made modular without breaking existing system. The modular nature of Java 9 would give the necessary boost for creating interesting systems.

Java 9 Features

Just like Java 8 is known as the major release of lambdas, streams and API changes, similarly Java 9 is all about project Jigsaw, utilities and changes under the hood. In this post, I would like to talk about some of the most exciting features being targeted for Java 9. The full list of new features is available here.

Modular System – Jigsaw Project

This is the biggest addition to the JDK and would bring modularity to the Java platform. An increase in codebase, quite often leads to complicated, tangled “spaghetti code”. It makes it hard to encapsulate code and there is no clear dependencies between different parts (JAR files) of a system. Any public class can access any other public class based on the classpath. This can lead to inadvertent usage of classes that were not supposed to be public API. In fact, the classpath itself is not an elegant way of verifying if the required JARs are present or it there are any duplicate entries. These challenges are handled very well by the module system.

The capabilities of a modular system are quite similar to those of OSGi framework. Modules have an inherent concept of dependencies, can expose a public API and keep implementation details hidden/private. The biggest motivation is to provide modular JVM, which requires lesser memory footprint in order to run on devices. The JVM can then run with only those modules and APIs which are essential.

There is an additional module descriptor in modular JAR files. This module descriptor, has dependencies expressed through “requires” statements. In addition to this, “exports” statements control which packages are accessible to other modules.

Modular JAR files contain an additional module descriptor. In this module descriptor, dependencies on other modules are expressed through “requires” statements. Additionally, “exports” statements control which packages are accessible to other modules. All packages which are not exported are encapsulated in the module by default. Let’s see an example of a module descriptor, which lives in ``:

module {


exports com.thistechnologylife.java9.modules.lawn;


The module house requires module furniture and exports a package for lawn.

JShell – The Interactive Java REPL

Jaba 9 comes with a new tool called “jshell”, which stands for Java Shell and also known as REPL (Read Evaluate Print Loop). It can be used to execute and test any Java Constructs like class, interface, enum, object, statements etc. very easily without wrapping them in a separate method or project.

JShell can be launched directly from the console and you can start typing and executing Java code. One great example of jshell is to test regular expressions.

The jshell executable itself can be found in <JAVA_HOME>/bin folder:


| Welcome to JShell -- Version 9

| For an introduction type: /help intro

jshell> "Say Hello To Java 9 Features".substring(13,19);

$5 ==> "Java 9"

Improved Network Communication with HTTP/2.0 Support

Java 9 comes with a new way of performing HTTP based communication. It provides a long-awaited replacement of the old HttpURLConnection and supports both WebSockets and HTTP/2. The new API is located under the package.

HttpClient client = HttpClient.newHttpClient();

HttpRequest request =





HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());

HttpClient also provides new APIs to deal with HTTP/2 features such as streams and server push.

Enhanced Process API

Process API had a limited capability to control and manage operating system processes. Even for getting process PID, you would need to either use native code or a tricky workaround. Not to forget, you would need different implementation for each platform.

In Java 9, the process API has been enhanced for controlling and managing operating-system processes. Most of the new functionality is present in the class java.lang.ProcessHandle. Process specific information can be obtained in the following manner:

ProcessHandle procHandle = ProcessHandle.current();

long PID = procHandle.getPid();

ProcessHandle.Info processInfo =;

Optional<String[]> args = processInfo.arguments();

Optional<String> cmd = processInfo.commandLine();

Optional<Instant> startTime = processInfo.startInstant();

Optional<Duration> cpuUsage = processInfo.totalCpuDuration();

As the example illustrates, the current method returns an object representing a process of currently running JVM. The Info subclass provides details about the process.

Now let’s see how we can stop all running processes using destroy method:

childProcess = ProcHandle.current().children();

childProcess.forEach(procHandle -> {

assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());


Stream API improvements

Java 9 brings significant improvements to the Stream API which packs a punch in creation of declarative pipelines of transformations on collections. Four new methods have been added to the java.util.Stream interface – dropWhile, takeWhile, ofNullable. The iterate method gets a new overload, which helps in providing a Predicate on when to stop iterating.

The takeWhile method takes a predicate as an argument and returns a Stream of subset of the given Stream values until that Predicate returns false for first time. If first value does NOT satisfy that Predicate, it just returns an empty Stream.

In this post I have tried to give a glimpse of some of the newly introduced features in Java 9. Trust me, we have just scratched the surface and there are many more useful and diverse features which would be available with Java 9. I am quite excited about this. What about you?