Book Image

Modular Programming in Java 9

By : Koushik Srinivas Kothagal
Book Image

Modular Programming in Java 9

By: Koushik Srinivas Kothagal

Overview of this book

The Java 9 module system is an important addition to the language that affects the way we design, write, and organize code and libraries in Java. It provides a new way to achieve maintainable code by the encapsulation of Java types, as well as a way to write better libraries that have clear interfaces. Effectively using the module system requires an understanding of how modules work and what the best practices of creating modules are. This book will give you step-by-step instructions to create new modules as well as migrate code from earlier versions of Java to the Java 9 module system. You'll be working on a fully modular sample application and add features to it as you learn about Java modules. You'll learn how to create module definitions, setup inter-module dependencies, and use the built-in modules from the modular JDK. You will also learn about module resolution and how to use jlink to generate custom runtime images. We will end our journey by taking a look at the road ahead. You will learn some powerful best practices that will help you as you start building modular applications. You will also learn how to upgrade an existing Java 8 codebase to Java 9, handle issues with libraries, and how to test Java 9 applications.
Table of Contents (19 chapters)
Title Page
Credits
About the Author
About the Reviewers
www.PacktPub.com
Customer Feedback
Preface

Java - the 20-year-old code base


Talk about a monolith! Java has come a long way since its first release in 1996. The first major release of the JDK had a little over 500 public classes. A far cry indeed from JDK 8 released in 2014, which counts upwards of 4,200 public classes and over 20,000 total files.

The following commands extract the rt.jar file, a library JAR file bundled in JDK 8, and count the number of classes in it. With the Java 8 version I have installed on my machine, the count is 20651:

The JDK and the runtime, the JRE, have continued to grow over the years. There are a lot of features that have been added to the language, so this growth is understandable. However, the Java language is also notorious for going to great lengths to maintain backward compatibility and for its reluctance to deprecate features unless it is absolutely necessary. So, in a way, the current size of the runtime is a little over what it could have ideally been.

Normally, most application developers wouldn't need to worry about the JDK code base. They just focus on their application code. However, the contents of the runtime does matter for application execution because of the way it is bundled. Traditionally, every JRE has had all the classes necessary for runtime bundled into a single JAR that resides in the lib directory called rt.jar. The name rt, as you might have guessed, stands for runtime.

Not only is this huge monolith of classes unnecessarily bulky in size, it also adds performance overheads for the Java Virtual Machine to manage. And that's a price the execution environment of all your applications have to pay, irrespective of whether all of those classes are being used or not.

Legacy classes

A good example of classes that you don't need is the set of classes in the JRE related to CORBA. Ever heard of CORBA? If you haven't, don't despair. It's for a reason! It's an old technology that was introduced to the Java runtime back in version 1.4. It has mostly fallen out of popular use since then. Considering most applications don't use the CORBA technology anymore, wouldn't it be great if apps could be bundled with JREs that do not contain the unnecessary CORBA classes?

That's unfortunately not possible, again, because of rt.jar. Since everything gets bundled into a single runtime JAR, you cannot pick and choose what features you need. Everybody gets everything. And since the runtime has been increasing in size, so has the standalone deployable application. This is a more significant challenge when the runtime needs to be used on smaller devices with limited resources. If you are bundling the runtime with a simple Hello World application that uses just a handful of classes from the runtime, you have no option but to bundle a whole lot of unused classes in rt.jar with it. And, yes, even those old CORBA classes join in for the ride!

Java 8 introduced the concept of profiles, and with that, you can technically deploy smaller runtimes. But they do have some drawbacks. Also, this feature was just an initial step in the introduction of modularity features in Java 9 anyway. We'll examine compact profiles in detail in Chapter 4, Introducing the Modular JDK.

Internal APIs

Remember the problem that Jack had with his BubbleSortUtil class? It was a Java class he wrote with the intention of it being private to his library. However, even though it started out as a private internal class, it ended up being a public class because other developers just decided to use it.

That was just a small library. Now, think about a library as big and as widely used as the Java runtime. The Java runtime obviously bundles in internal classes that are required for its functioning and aren't meant to be used by application developers. However, considering the magnitude of its usage, it isn't surprising that some of the internal classes are inadvertently used by developers anyway.

A classic example of this is a class called Unsafe in the sun.misc package. This ominous sounding class has been a part of every major JDK release for a while now. Can you guess what it does? It contains a collection of methods that perform, according to the author of the class, low-level unsafe operations. Yes, it actually says that in the comments in the class! For instance, it has a method that gets a value from a memory address. Not a typical day's work for a Java application developer! You wouldn't, and ideally shouldn't, do something like that as an application developer. This is why the class has been marked as an internal API. Want to look up its Javadoc to use it? You won't find it in there. Want to create a new instance of the class? Its constructors are marked as private. If you do somehow use it and compile your code, every Java compiler since Java 6 will give you a nasty warning, discouraging the usage of the class. And, if you still need more reasons to avoid using it, you'd be best served to just look at the name of the class!

You must have guessed what's coming by now. The sun.misc.Unsafe class has now been used in multiple projects by many developers to perform those very low-level operations, in spite of all those preventive measures that the Java runtime authors have put in place. One could argue that it implements functionality that isn't commonly available elsewhere, and for a developer who needs to do something like that, nothing beats just picking it up while it's available in the classpath and ready to use. Unsafe isn't the only internal API that is being used this way, of course. There are a few more internal classes, many in the sun.* packages, that developers have used over the years even though they shouldn't. Moreover, as long as developers continue to use these APIs, it becomes harder to remove them from the runtime. This has ended up continuing the existence of these classes in subsequent versions of the runtime, thereby allowing more developers to use them!

These limitations of the Java runtime and library system have been felt for a while now. All the problems I've outlined so far exist because of the lack of ability to create modular units of code in Java. Such a construct simply hasn't existed in the language so far. The need for it has been strongly felt in the community.

Multiple proposals for a module system for Java have been made over the years, including JSR-277 way back in 2005 (https://jcp.org/en/jsr/detail?id=277) and JSR-294 (https://jcp.org/en/jsr/detail?id=294) in 2006. After facing several hurdles, modularity is finally coming to Java with the 2017 release of Java 9 with JSR-376 (https://jcp.org/en/jsr/detail?id=376), the spec titled Java Platform Module System, as well as Project Jigsaw.

Note

Acronym alert: JCP and JSRJCP: The Java language specification has, for a long time, been a community-owned asset. There is no one central authority that has complete control and the decision-making power in how the language evolves. Each of us, as Java developers, can have a say in how we want the language to change and grow. The Java Community Process (JCP) is a mechanism, introduced in 1998, that allows anyone interested in the future of the language specification to register, provide input, and take part in the technical specifications process. Go to https://jcp.org to learn more.JSR: Let's say you are a part of the Java Community Process, and you have a great idea for a change in the language specification. What you do is create a Java Specification Request (JSR)--a formal document that describes the proposed changes. JSRs are reviewed and voted upon as a part of the community process before they become final. Once a JSR does become final, it is worked on and eventually becomes a part of the language specification. Fun fact: The Java Community Process itself is an important part of the language, and so changes to it are also handled just like any other changes to the language--by submitting a Java Specification Request for it. Yes, there's the JSR that describes the JCP!