© Alexandru Jecan  2017

Alexandru Jecan, Java 9 Modularity Revealed, https://doi.org/10.1007/978-1-4842-2713-8_2

2. Project Jigsaw

Alexandru Jecan

(1)Munich, Germany

This chapter introduces Project Jigsaw. It describes what Project Jigsaw is all about, shows some problems encountered in the past in Java, and discusses the Java Enhancement Proposals that constitute Project Jigsaw. It explains the goals of Project Jigsaw so that we can get a grasp of the reasons that made the JCP team decide to introduce a new module system for the Java platform. It also goes over concepts like strong encapsulation and reliable configuration.

Weaknesses in Java Prior to JDK 9

Figure 2-1 shows the JDK 7 module graph, from the official OpenJDK website at http://openjdk.java.net/projects/jigsaw/doc/jdk-modularization.html . The base module is displayed right in the middle. Because there were a lot of dependencies between the classes, there was no way to split the monolith into smaller pieces . Besides that, the access delimiters didn’t provide sufficient means to completely hide the implementation of the classes. Their scope was limited. For instance, in JDK 7 if we wanted to print “Hello world!” using the System console, we would need a great number of packages besides the base module.

A431534_1_En_2_Fig1_HTML.jpg
Figure 2-1. The module graph in JDK 7

JAR (Java Archive ) files are ZIP files that contain class files and other resources. One or more JAR files are placed on the class path, which doesn’t provide encapsulation for the JAR files it contains. This means that every class in a JAR file is accessible by every other class, and that represents a security vulnerability. You can imagine the class path like being a row where the JAR files are being searched linearly from left to right. JAR files are not components that can provide modularity for the classes that they contain.

Introduced in JDK 8, compact profiles are a subset of the full Java SE platform. The three compact profiles are called compact 1, compact 2, and compact 3. A list of the packages contained in each compact profile is listed on the Oracle website. The compact profiles were just a small step toward the modularization of the platform. Being able to get three different versions of the JDK by aggregating the standard packages was not what the community expected with respect to modularization. Besides that, compact profiles don’t hide their internals and therefore brought no improvements to the security of the Java Platform.

Explicit dependencies were also a huge problem before Java 9. By packaging source code in a JAR file and putting it on the class path, there was no way of programmatically defining which other JARs were needed in order for the actual JAR to be able to run. Because Java didn’t solve this problem, a few popular build tools have emerged, including Maven and Gradle.

Weak Encapsulation

For achieving encapsulation, Java prior to version 9 used the well-known access modifiers: private, protected, public , and no modifier. The private access modifier is the most restrictive . It makes the data inside unavailable from outside. The protected access modifier indicates that the member can only be accessed by a subclass of its class in another package or within its own package. The public access modifier makes data available everywhere. Using no access modifier means that availability is granted only inside the same package.

However, encapsulation has some limitations. It’s impossible to make a type accessible to an external package and at the same time restrict access to it from all other existing packages. To make the type available to an external package, the only way would be to mark it as public, although defining it as public breaks encapsulation and makes it public for all the existing packages. There is no way to reach the desired level of encapsulation using Java prior to version 9.

JAR Hell Problem

Prior to JDK 9, the standard style for developing Java applications was to insert all the necessary libraries and JAR files directly on the class path. This approach could give rise to the JAR hell problem.

Before JDK 9, the runtime environment searched on a couple of locations in order to load a class. One of the searched locations is the class path , which contained a list of class files that were loaded by the Java Virtual Machine. Searching for a class on the class path was straightforward. The class loader searched a class by exploring all the JAR files listed on the class path. It didn’t take into account a pre-definite order but just searched from the first to the last. It also didn’t take into account aspects of the internal structure of the classes on the class path. Java wasn’t able to take the boundaries between the JAR files into consideration. All the classes from all the JAR files were placed on the class path, and the boundaries between the JAR files disappeared. Each type in a JAR could access all the public types from any other JAR files. Therefore, the code couldn’t be encapsulated in order to hide it from external use.

We’ll give you an example. Suppose an author of a library had some internal code in the library that was never intended to be used from outside. Because there was no encapsulation, everyone could access this internal code—and worse, provide an own implementation that depended on the internal code. If the author of the library decided to make some changes in the internal code of his library, then code that depended on this library might encounter issues.

JAR hell is a common problem encountered prior to JDK 9. If there were more libraries on the class path with different versions and each library depended on another library, then there was said to be a JAR hell problem on the class path. This so-called dependency hell happened when a package had a dependency not on another package , but only on a version of that package. There were different variations of dependency hell, taking into account the environment being used. The problem with JAR hell is that you could have conflicts on the class path, especially when it contained many JARs. For instance, one library could have two or more different versions of a specific class on the class path. The class path wasn’t the best solution because JAR files aren’t components, and therefore we can’t exactly know if something is missing or is conflicting.

If a specific class wasn’t found on the classpath, a runtime exception was triggered—not during the launch of the application but at a later point when, due to an action performed by the user, the missing class was invoked. The runtime didn’t have the capacity to identify all the existing dependencies until it had to access them. It would have been preferable to have all the errors displayed right during the start of the application and not at a later point .

What Is Project Jigsaw?

Project Jigsaw represents the implementation of the new scalable module system introduced in Java 9. It was developed under Open JDK, which is the free , open source implementation of the Java Platform Standard Edition. The goal of the newly designed module system for the Java SE Platform is to modularize the JDK and apply the module system to the JDK itself. Jigsaw modularizes the Java SE platform.

The process of modularizing the Java platform was a complicated and tremendous effort. A great number of difficult design decisions had to be made. The modularization of the platform is an enormous change with a major impact on the entire ecosystem. It introduces the new concept of modules and significantly changes the way we develop software applications using the Java programming language. Modules are placed in the foreground and are the key concept upon which Project Jigsaw is based. Entire programming techniques have to be adjusted to match the newly introduced concept.

Project Jigsaw started back in 2008 in an exploratory phase. The JEPs that constitute the Java Platform Module System were created starting with year 2014. Project Jigsaw was initially planned for the Java 7 release, but due to its complexity it was not included in the JDK 7 release and was postponed for the JDK 8 release. Then the Java Community Process deferred it for Java 9. Although the official release of Project Jigsaw is at the time of this writing planned for September 2017, early access builds have been available for a long time on the Open JDK website so that the community can test and provide valuable feedback to the JDK developers.

Project Jigsaw consists of six JEPs and a JSR. JSR 376 is called the Java Platform Module System . It designates a standard specification for building a modular version of the Java platform. Table 2-1 lists the other six JEPs that are part of Project Jigsaw.

Table 2-1. JDK Enhancement Proposals (JEP) for the Development of the Java Platform System

JEP Number

JEP Name

Scope

JEP 200

Modular JDK

Standard Edition

JEP 201

Modular Source Code

Implementation

JEP 220

Modular Run-Time Images

Standard Edition

JEP 260

Encapsulate Most Internal APIs

Java Development Kit

JEP 261

Module System

Standard Edition

JEP 282

jLink: The Java Linker

Java Development Kit

Following are short descriptions of each of the JEPs. They’re covered in greater depth in the chapters that follow:

  • JEP 200—the Modular JDK: This Java Enhancement Proposal divided the JDK into a set of modules. The JDK was modularized, and the source code was organized into modules. There are two different categories of modules: standard modules, with names that start with java., and JDK modules, that start with jdk. A new module graph emerged as the modular format of the JDK changed (shown in Chapter 3). More information about the JDK modularization can also be found in Chapter 3.

  • JEP 201—Modular Source Code: This JEP defines how the JDK build and the source code were reorganized around modules (covered in detail in Chapter 3).

  • JEP 220—Modular Run-Time Images: JEP 220 presents the new modular runtime image and the enhancements added so that we can build custom modular runtime images. The binary structure of the JRE and JDK was changed. The JEP is discussed in Chapter 5.

  • JEP 260—Encapsulate Most Internal APIs: JEP 260 refers to the process of encapsulating the non-critical internal APIs. This JEP is covered in many chapters throughout this book.

  • JEP 261—Module System: JEP 261 represents the implementation of the new module system.

  • JEP 282—jLink: The Java Linker: This JEP creates a tool that assembles a set of modules into a custom runtime image (covered in Chapter 7).

Downloading and Installing

As of September 2017, an early-access version of Project Jigsaw can be downloaded from the following URL address: http://jdk.java.net/9/ . Project Jigsaw is contained into JDK 9. It cannot be used separately.

JDK 9 is available for download for the following platforms:

  • Windows 32-bit

  • Windows 64-bit

  • Linux 32-bit

  • Linux 64-bit

  • Solaris SPARC 64-bit

  • Solaris x86 64-bit

  • Mac OS

Project Jigsaw was merged into JDK 9, so if you download JDK 9, you will have Jigsaw included by default .

The installation is straightforward. You have to set the environment variables on your PC to point to the new JDK. For this, choose the root folder where your Java 9 installation resides. If you use Windows and JDK 9 is in the PATH, you can verify that the environment variables have been successfully set by opening a command line and typing java -version.

Documentation

There is plenty of documentation available for Project Jigsaw on the official Open JDK website at http://openjdk.java.net/projects/jigsaw . You’ll find descriptions for each of the JEPs that constitute the Java Platform Module System. The specification document can be found at http://openjdk.java.net/projects/jigsaw/spec/reqs/ .

To get more deep insight into Project Jigsaw, you can access the Jigsaw Development mailing list, which contains comprehensive information about the internals of Jigsaw, at http://mail.openjdk.java.net/pipermail/jigsaw-dev/ . Other mailing lists that might interest you are the Expert Group mailing list at http://mail.openjdk.java.net/pipermail/jpms-spec-experts/ and the Adoption Discuss mailing list at http://mail.openjdk.java.net/pipermail/adoption-discuss/ .

The API Specification for the Java 9 Standard Edition can be found at http://download.java.net/java/jdk9/docs/api/overview-summary.html .

Goals of Project Jigsaw

The goals of Project Jigsaw , as listed on the Open JDK website at http://openjdk.java.net/projects/jigsaw/ , are as follows:

  1. To make the Java SE Platform and the JDK more easily scalable down to small computing devices

  2. To improve the security and maintainability of Java SE platform implementations in general and the JDK in particular

  3. To enable improved application performance

  4. To make it easier for developers to construct and maintain libraries and large applications, for both the Java SE and EE platforms

The module system should be powerful enough to modularize the JDK and other large legacy code bases, yet still be approachable by all the developers.

The module system split the Java platform into modules that can be managed by users. Modules can hide their internal implementation but still interact together efficiently. They have the ability to manifest explicitly if they’re entirely accessible to other modules, if only some parts of their types are accessible to other modules, or if they’re not accessible to other modules at all. They can also specify the list of modules to which they’re available. These Java 9 features are called reliable configuration and strong encapsulation and are achieved in an easy way.

The problems related to JAR hell on the class path are solved by using the new module path instead of the class path. The JDK maintenance and administration is reduced by encapsulating the internal APIs. Project Jigsaw masks some of the internal APIs of the JDK by taking advantage of the strong encapsulation mechanism. The public types in the JDK internal APIs’ packages are a lot harder to access, which leads to breaking code in some applications that are using internal APIs.

Let’s look at the motivation behind the decision to develop Project Jigsaw. At the beginning of the project, the goal was, according to Open JDK, “to design and implement a module system focused narrowly upon the goal of modularizing the JDK, and to apply that system to the JDK itself.”

Before Java 9, JDK was a big, indivisible monolith with more than 5.500 classes. It was impossible to split it into more pieces. The only way to use it was to install it entirely on the target platform. The Java runtime represented by the rt.jar file was also monolithic and couldn’t be split into more parts. JDK consisted of rt.jar , which contained almost all the compiled classes for the base Java runtime. rt.jar grouped together all the runtime class files and had to be placed on the class path in order for the user to be able to access the Java API classes. Inside rt.jar there were—besides the popular java.* and javax.* packages— other packages such as com.oracle.*, com.sun.*, jdk.internal.*, jdk.management.*, jdk.net.*, sun.*, and more. There was no way to split rt.jar into different files. In Java 9, the focus was to break the monolithic JDK into modules and to completely remove the rt.jar file.

The JDK had to be modularized because, after more than 22 years since its first release, it had grown so much that it effectively became too big and too complex. Installing JDK on small devices can be cumbersome in certain situations, because not all small devices have enough CPU, memory, or disk space to be able to hold the entire JDK. Besides that, it’s a huge waste of memory to install the entire monolithic JDK and use only a small portion of it in your application. This problem relates not only to small devices, but to big devices as well, like the ones used to hold the applications in the cloud. Important additional costs could occur using the cloud because the use of hardware resources isn’t optimized.

JDK 1.0, released at the beginning of 1996, was extremely small and tiny in comparison to the actual release of the JDK . The first version of Java had only a few standard packages: java.lang, java.io, java.applet, java.awt, java.net, and java.util. There were a total of 8 packages and 212 classes and interfaces. Every release after JDK 1.0 added more and more complexity. JDK 1.1 had 504 classes and interfaces. JDK 1.2, released in 1998, tripled the number of classes and interfaces to 1,520. During the next JDK releases, this increase continued: JDK 1.4 had 2,991 classes and interfaces, and JSE 8.0 had 4,240 classes and interfaces. Compared to JDK 1.0, the release of Java 8 contained exactly 20 times more classes and interfaces. Besides the big size, the JDK prior to version 9 was very complex due to the dependencies between the APIs.

Previous to JDK 9, for a simple program that prints a string in the console, a great number of classes had to be loaded. For example, the base module in JDK 7 depended on a lot of other modules such as logging, security-smartcardio, security-sunec, security-resources, resources, charsets, client, security-misc, security-jsse, security-kerberos, and others. All these modules had to be loaded in order to print a basic and very simple “Hello world!” in the console.

Taking into consideration all the facts previously mentioned, the decision to work at splitting the JDK into modules was absolute necessary. A modular JDK reduces the number of classes loaded because there aren’t any dependencies or connections between classes from different modules anymore. Java 9 also improves the startup time of Java applications , and the memory footprint in Java 9 is better than in previous releases.

New Concepts Introduced in Jigsaw

Project Jigsaw introduces the new concept of module as a central software component that is built inside the Java platform. A module represents a collection of packages. It has a module descriptor that specifies the modules upon which the module depends and also specifies its exported packages that are made available for external use. A module can be packaged into a new format called modular JAR, which is a JAR file that also contains a module-info.class file. A modular JAR file can function as a module in Java 9, but also as a regular JAR file on the class path in Java 8 or earlier. There’s another new format called JMOD , which is similar to a modular JAR but can also contain native code. A module can be open or not. Chapter 4 describes modules in detail.

The new notion of module path is introduced in Project Jigsaw. Module path is the module equivalent of the class path and consists of a list of directories that contain modules. Upcoming chapters cover the module path and show you how to use it alone or in combination with the class path.

Jigsaw also introduces a linking phase in which a group of modules is assembled by a new linking tool, called Jlink (covered in Chapter 7), into a custom binary runtime image. Linking can create a full Java development environment and can also create a Java runtime system incorporated in a program.

Java 9 adds many new options for both the Java compiler and the Java launcher in order to allow the compilation and running of modules. Throughout this book you’ll find plenty of examples of compiling and running modules using different command-line options. Jigsaw also introduces new notions like unnamed module, open module, and automatic module, all covered in Chapter 4.

Strong Encapsulation

According to the official Jigsaw specification, “strong encapsulation allows a component to declare which of its public types are accessible to other components and which are not.” Strong encapsulation’s role is to forbid code from accessing classes in packages that aren’t exported by their containing modules, or in packages whose containing modules aren’t needed by the module that contains the code.

Strong encapsulation couldn’t be achieved without having a concept like modules, because in Jigsaw the modules represent the base on which the principles of strong encapsulation are applied. Jigsaw allows modules to export only specific packages. The accessibility of modules is provided by their boundaries. Strong encapsulation is accomplished in Jigsaw using the definitions of the modules, where we are able to specify what types are accessible. Strong encapsulation hides module’s internals and prevents them from external access. It also makes it more difficult to achieve reflective access.

In Java 9, calling the method setAccessible() won’t work unless the object is accessible before the class. To be accessible, the corresponding package has to be exported, and the module has to be read. If both conditions are met, then it is accessible, so the method can be applied to make, for instance, a private field available. Strong encapsulation restricts access even when the accessing class in the target class is in the same class loader . By the way, strong encapsulation is not dependent on class loaders.

Reliable Configuration

Reliable configuration is a strong feature introduced in JDK 9. Open JDK states that “reliable configuration replaces the class path mechanism with a means for program components to declare explicit dependences upon one another.” Reliable configuration is based on the capacity to declare dependencies between modules. It allows us to know at compile-time if a module is missing or a dependency isn’t fulfilled. This is something we could’t achieve in versions before Java 9. In JDK 9, modules can manifest their dependencies on other modules, and the module system certifies that every module dependence is achieved.

The ground for reliable configuration is represented by the readability connections that exist in the module system. Dependencies are analyzed and enforced at both compile-time and runtime. In chapter 4 you’ll learn how reliable configuration is achieved in Jigsaw by the requires clause and how strong encapsulation is achieved by the exports clause in the module declaration .

Enhancements Provided by Jigsaw

Jigsaw also provides enhancements in three important areas: security, scalability, and performance.

Security

Java had a considerable amount of security issues in the past. Prior to JDK 9, as mentioned, there was no encapsulation across package boundaries. Hence, security is a very important subject in Jigsaw, being one of the key factors in some of the implemented design considerations. In Java 9, some portions of the code can’t be accessed directly anymore. Jigsaw improves security significantly and greatly reduces the security risks by hiding the JDK internal APIs. We call this the encapsulation of the JDK internal APIs. They can now be handled only within the JDK itself. To improve security, it was not enough to only encapsulate the JDK internal APIs—its number of uses was decreased too. By specifying module boundaries, code is no longer reachable from outside of the module unless it’s explicitly defined so. By default, it’s not reachable from outside.

Security is improved by the newly introduced strong encapsulation mechanism, which hides module’s internals. Critical source code is hidden and is not accessible from outside unless absolutely necessary. Attempting to access a public JDK internal type results in an access error. This is why code that uses internal APIs no longer works starting with Java 9.

In Jigsaw, the mechanisms that allow access to internal classes using reflection have been hardened. This is a great improvement because in the past the benefit of accessing internal JDK classes resulted in many security incidents in the Java platform. As the number of internal JDK classes decreases in Java 9, so do the number of potential breaches.

Prior to JDK 9, Java had a serious issue regarding the fact that its classes were accessible from external code running in the same environment. It had very limited ways of restricting the access to its code from outside. In order to restrict package access, Java used the method checkPackageAccess(String packageName) of class java.lang.SecurityManager. This method gets a list of restricted packages from calling java.security.Security.getProperty("package.access") and checks whether the parameter packageName is between the retrieved packages. If not, then the method throws a SecurityException. If packageName is found, then the method checkPermission() is called. Some of these security problems from the past were related to the fact that the software developers sometimes forgot to call the checkPackageAccess() method in code everywhere it was necessary. If this check isn’t done everywhere, then the code can be accessed from outside and a big security breach is opened, causing potential damage. It was the responsibility of every JCP developer to be careful and not forget to put the checkPackageAccess() call everywhere it was necessary .

Scalability and Performance

Jigsaw allows developers to create their own Java Runtime Environments (JREs) that contain only the modules they need. A great number of small devices benefit from the prospect of being able to group only the functionality that is strictly required by the running Java software application.

Performance is enhanced during the class loading process because the Java Virtual Machine now knows where the location of a class is. Because we know in advance all the classes that a class refers to, the JVM can eventually perform optimizations that will result in a performance increase. Before Java 9, the JVM had to open every JAR file and perform a linear search in order to find a class, which imposed a huge cost on performance.

The removal of rt.jar in Java 9 was a good design decision with respect to performance because it allowed the introduction of a new productive storage system. The performance of Java applications has been improved in Java 9, especially at startup time. For this, the structure of Java runtime has been modified. There’s now enough potential for future performance optimizations because portions of code are reached only by the modules they depend on.

The degree of scalability of the Java platform is increased by allowing developers to create smaller and more optimized deployments that help reduce the amount of memory needed on the corresponding running device. The new custom runtime images contain only the specific libraries and the minimum number of dependencies needed to run a Java application. There’s no longer a requirement to install the entire JDK. It’s possible to select exactly the modules needed by an application.

Other Generalities

New Keywords in Java 9

Module is a restricted keyword that acts like a keyword only in relation to a module declaration. When a module isn’t used in connection with a module declaration, then the word module can further be used as an identifier. This means that if we used the word module to define the name of a variable, an instance variable, or a method, we don’t have to change it.

Other restricted keywords introduced in Java 9 include exports, requires, provides, uses, with, to, transitive, and opens.

No Versioning in Jigsaw

Versioning is not supported in Project Jigsaw . The JCP team included versioning in the first releases of Jigsaw but then decided to leave it out due to the complexity and complications that subsequently occurred. The decision was based on the fact that build tools like Gradle or Maven have better mechanisms to handle this complicated problem. Project Jigsaw relies on these build tools for solving versioning resolution or dealing with different conflicts. Jigsaw allows you to declare a version in the meta information of a module, but this version isn’t taken into account by the module system. Chapter 10 talks about layers, and you’ll learn how Jigsaw can load two different versions of a module. Hence, these are all the features that Jigsaw brings for versioning. For instance, declaring in a module declaration that a module dependends only on a specific version of another module isn’t supported.

Backward Compatibility

Having backward compatibility to older versions of the JDK was a critical topic during the design of JDK 9. The JCP team states, “if an application uses only supported APIs and works on release X, then it should work on release X+1 even without performing a recompilation.” Fixing the incompatibilities inside the source code is mandatory in order to make a Java software application work after moving to Java 9.

The requirements of Project Jigsaw, published on the Open JDK page, state: “It must be possible to divide an existing Java Platform, Java SE or Java EE, into a set of modules such that existing libraries can run without change, so long as they use only standard platform APIs.” Java applications will be backward-compatible with versions prior to JDK 9 as long as they use only standard platform APIs. If they’re using other APIs besides the standard ones, there’s no guarantee they’ll work in JDK 9.

Some compatibility problems could appear for applications or libraries that use core reflection to gain access to JDK internal types. For the builds to work, using the command-line flag --add-exports is mandatory in order to break encapsulation. This command-line option is covered in Chapter 8.

Another issue can occur when an existing library from the class path has a reference to a type in a non-exported package that belongs to an explicit module. In order to solve it, using the class path in combination with the module path is required. In upcoming chapters you’ll learn how to achieve that. It’s important to remember that, for having backward compatibility, the class path can be further used in JDK 9.

Nevertheless, in order to provide backward compatibility , the three class loaders are still present in JDK 9. Chapter 10 talks about them.

Platform Modularization

One of the most important roles of Project Jigsaw is to split the JDK into modules, explained in detail in Chapter 3. The resulting modules can be divided into three distinct categories: standard modules, JDK-specific modules, and JDK-internal modules.

Before Java 9, rt.jar contained many publicly accessible APIs that were planned for public use. It was possible to use them when writing your own code. Among the publicly accessible APIs there are plenty that are part of the standard Java SE. These packages start with java.* and javax.* and are specified by JCP. Other packages that form the publicly accessible APIs, but are not part of the standard Java SE, are the jdk.* and com.sun.* packages. These packages are not part of the standard Java SE because they’re intended to be used by tools that interact with the Java Virtual Machine, for instance. It doesn’t make sense to make them part of the standard Java Standard Edition.

Besides the supported APIs, there are also unsupported APIs . Most of them reside in the sun.* package. They’re not meant to be used publicly. A survey organized by Oracle revealed that the most popular unsupported APIs are sun.misc.Base64Encoder, sun.misc.Unsafe, and sun.misc.Base64Decoder. Oracle classified the APIs based on their usage and organized them into critical and non-critical. The non-critical APIs have very little usage outside the JDK .

New Structure of the JRE and JDK

In order to provide the means for creating runtime images, the binary structure of the JDK and JRE was changed in Java 9. Due to the introduction of modules, there’s no difference between the JDK and the JRE. Every tool that depends on rt.jar had to be changed in order to work further properly in Java 9.

Figure 2-2 illustrates the old structure of the JDK and JRE, prior to Java 9.

A431534_1_En_2_Fig2_HTML.gif
Figure 2-2. The structure of the JDK prior to Java 9

Before JDK 9, there were two bin and two lib directories. The lib directory from the top level contained classes for tools, and the lib directory from the jre directory contained the runtime classes. The lib directory also contained configuration files, security policy files, and other types of files.

Figure 2-3 shows which files and directories have been completely removed in JDK 9: the jre directory, the tools.jar file, and the rt.jar file.

A431534_1_En_2_Fig3_HTML.gif
Figure 2-3. The jre directory, tools.jar, and rt.jar were removed in JDK 9

Figure 2-4 depicts the final structure of the JDK 9.

A431534_1_En_2_Fig4_HTML.gif
Figure 2-4. The new layout of JDK 9

As you can see, the jre directory doesn’t exist anymore, and a new conf directory was added. The conf directory contains the configuration files that customize the JDK or the runtime. It contains only the files that should be edited. The files that should not be edited are not located in the conf directory anymore. This is important because the new layout provides a clear separation between the configuration files that are allowed to be changed and the ones that aren’t. In the past it was a risk to change a configuration file because you couldn’t know in advance if you were even allowed to change it, meaning the application might not start anymore.

The rt.jar and tools.jar files have been completely removed. The bin directory, which is now a single one, contains all the launchers. The new format of the JDK is more suitable for future optimizations than the old format .

How to Prepare for Jigsaw

There are some steps that you should perform in order to prepare for Project Jigsaw. As you already know, the JDK-internal classes aren’t accessible any more, unless they’re part of the package jdk.unsupported. Code that relies on JDK-internal classes will break.

First of all, you should check your code for uses of JDK-internal APIs using JDeps . JDeps is a tool for analyzing and finding statical dependencies (it’s covered in detail in Chapter 8). If you find uses of JDK-internal classes throughout your code, you should provide replacements for them. JDeps gives you hints and proposes alternatives for your JDK-internal classes, but it’s your responsibility to get rid of these classes and replace them with supported ones.

The Java compiler command-line option --add- exports is an alternative if you can’t provide replacements for the JDK-internal classes. This command breaks the encapsulation and makes the JDK-internal classes accessible in your code. In this way, you don’t have to modify your source code—you just have to adapt your build scripts to include this option during the compilation of your code.

Besides the uses of the JDK-internal classes, you should also check your code for dependencies on the rt.jar and tools.jar files. Both files were removed in Java 9, and code that relies on them will stop working. You can’t use them throughout your code anymore in Java 9 .

Another important topic refers to the split packages, which should be definitely avoided. Split packages arise when two or more loaders designate classes for a single package. You have to get rid of the split packages before migrating to Java 9. Chapter 8 covers the split packages problem in detail and shows you how to get rid of them.

Migrating to Java 9 can be challenging under some circumstances. That’s why we cover this topic in more detail in Chapter 8. The list just presented isn’t complete. If you want to know more about how to prepare for using Jigsaw , go directly to Chapter 8.

Differences Between OSGi and Jigsaw

OSGi (Open Service Gateway Initiative) is a well-known framework that allows developing modular applications in the Java programming language. The specification for implementing module systems in Java using OSGi can be found in the document JSR 291 – Dynamic Component Support for Java SE, which was released in August 2007.

We won’t go deep into detail regarding OSGi because OSGi is beyond the scope of this book, but we will present some important distinctions between it and Jigsaw. One major difference between OSGi and Jigsaw is the fact that OSGi supports versioning, but Jigsaw does only at a low degree. Jigsaw allows you to define a version as a meta attribute or to use multiple versions for a module in a layer. But the versioning system offered by Jigsaw is far less powerful than the one offered by OSGi. OSGi also has some features related to dynamic life-cycle that Jigsaw does not have. Besides this, OSGi provides a dynamic service registry and an upgraded security model.

Jigsaw is more secure than OSGi because its security mechanism can’t be bypassed. The security mechanism from OSGi can be bypassed. The OSGi bundles don’t give the same level as security compared to the Jigsaw modules.

Jigsaw isn’t intended to be a replacement for OSGi. OSGi can operate very well on top of JDK 9. JCP aims to make both systems able to work in parallel and to cooperate. It should even be possible for OSGi to treat a Jigsaw module as an OSGi bundle.

There may be specific cases when OSGi is more suitable to the needs of an application than Jigsaw. Jigsaw is more suited for software applications that don’t present an extremely high level of complexity. OSGi takes advantage of true isolation because it’s built on top of the platform. Both OSGi and Jigsaw provide isolation, but the way that’s achieved differs. In OSGi, isolation is achieved automatically because OSGi is built on top of the platform. In Jigsaw, the modules have been built inside the platform, not on top of it. They present isolation programmatically by the manner in which they are designed into the platform.

In general, Jigsaw has fewer features than OSGi. For instance, Jigsaw doesn’t offer the possibility to dynamically download and load modules from a repository when an application and the virtual machine are running. This kind of feature doesn’t exist in Jigsaw, and OSGi should be used instead for this specific case.

Project Jigsaw also offers important features that don’t exist in OSGi, such as modularity at compile-time and built-in support for native libraries. Jigsaw, in contrast to OSGi, modularizes the Java platform and introduces the new concept of modules as a central program element .

Summary

We started this chapter by presenting some weaknesses and problems that occurred prior to Java 9, such as weak encapsulation and the Jar Hell problem. Then we introduced Project Jigsaw, the new module system introduced in Java 9, and described the goals of Project Jigsaw and some of the problems it solves. The chapter briefly presented a couple of new concepts introduced in Jigsaw.

We talked about the strong encapsulation and reliable configuration mechanisms introduced in Jigsaw, which make a public type not accessible from outside of its module unless it’s in an exported package. We also described other enhancements provided by Jigsaw in the fields of security, scalability, and performance. Prior to JDK 9, it was much more difficult to maintain our code because we couldn’t encapsulate it in order to hide our internal implementation from external use.

The next topics were backward compatibility and platform modulatization, and we provided insights into the new categories of APIs in the JDK. Then we presented the new structure of the JRE and JDK in Java 9 and talked about the removal of rt.jar and tools.jar. Next we outlined some of the most important steps you have to take in order to prepare for using Jigsaw in your projects. The end of the chapter illustrated some of the most important differences between OSGi and Jigsaw.

Chapter 3 describes the JDK modularization process, the resulting modular JDK, and the way source code was modularized in JDK 9.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.12.140