Finally: Java 9
Land Ho!
For a long time, Java [1] has easily topped the rankings of popular programming languages. This is not surprising; after all, programs developed in Java can be used anywhere from cellphones to mainframes and across all operating systems. However, a glimpse at the former shooting stars Perl and PHP shows that there is no guarantee of permanently riding atop the heap.
Regular updates help keep the language at the cutting edge and the estimated nine million Java programmers happy, but they have needed patience, because major release 9 has taken its time. Originally, it was planned as an interim release to deliver to the themes that were not ready in time for Java 8.1. "As quickly as possible" originally meant mid-2015, then mid-2016, and finally 2017. It remains to be seen whether the project schedule will be followed this time, although test builds are now available online [2].
Jigsawing
One core feature of Java 9 par excellence is the Java Platform Module System that became known as Project Jigsaw [3]. Thus far, the Java compiler and the run-time environment have thrown all available libraries from the class path into a large pot. Whether this turns out to be a tasty soup or smoke and mirrors partly depends on subtle changes in the class path.
Many developer hours have been spent in class path hell battling against the class loader. The problem is, only the right libraries and library versions in the appropriate order result in a working application. Approaches such as Maven, ServiceLoader
or OSGI only partially mitigated the situation and had to take a wide detour around the standard libraries.
With Jigsaw, this should be different. The new modular system pervades the entire stack of the compiler, from the Java Runtime Environment (JRE) and the standard libraries to the application libraries. The development effort for Jigsaw was originally estimated to be about size XL, but in the real world, a number of Xs were added. The initial plans had their sights set on Java 7.1; ultimately, Jigsaw now first appears in Java 9. All three affected versions were delayed by years.
Totally Modular
The result is not only improved handling of libraries, but modularization also allows developers to tailor the JRE to the needs of an application. After all, the standard libraries in Java 8 weigh in at around 60MB and 20,000 classes. They not only need space on the hard drive, but the computer also needs to load them into memory at every startup and check the classes and methods they contain. Less powerful machines (industrial automation, IoT, network appliances) welcome every single megabyte saved, so the application uses less space and launches faster.
Java 9 dismantles the monolithic standard library modules. If you do not need features such as the CORBA stack, the JavaScript interpreter, or encrypted XML documents, you will soon have the opportunity to tailor the installation to your own needs for the first time.
A Scenario
The scenario shown in Figure 1 is used as an illustration of the new modular strategy. The sample application consists of two proprietary modules (modulea
and app
). Also on board are two modules from Java itself and another two for logging.
The modulea
module includes everything related to the Customer
business object. It contains a Customer
interface, the matching CustomerService
for searching and saving, and the associated implementation (Impl
) classes. For this purpose, the software needs classes from the modules java.core
, java.xml
, and slf4j.core
. The app
module contains the application itself and requires modulea
plus logback.core
; the modules required in moda
are implicitly available.
At the file level, modules are ordinary Java archives in JAR format that additionally contain a description of the module. They each provide module_info.java
files that the developer compiles with the other classes and bundles into the JAR.
Listing 1 shows the module description for modulea
. The declaration starts with the module
keyword; the requires
point to the code to the necessary modules. The compiler and the JRE use this to load the modules or to inform the user that they are missing immediately on startup. For modules like app
to be able to use the two interfaces, the module description releases the contained package using export
.
Listing 1
modulea description
01 module de.lm.java9.modulea { 02 // required 03 requires java.base; 04 requires java.xml; 05 requires slf4j.api; 06 07 // exported 08 exports de.lm.java9.modulea; 09 10 // provides a service implementation 11 provides de.lm.java9.modulea.CustomerService with de.lm.java9.modulea.intern.CustomerServiceImpl; 12 }
All other classes from modulea
are not visible outside of the module. Although the CustomerImpl
class is declared as public
, the contained package cannot be reached outside of the module because of a missing export
. In this way, developers could enforce loose coupling so that the user of a library sees its interfaces but has no access to the actual implementation or helper classes.
Ultimately, access to the object instances of the exported interfaces are needed somehow. Putting the CustomerService
implementation in the public package would be contrary to the idea of loose coupling, because a user of the objects should not have to worry about how this is implemented. Here, the well-known but little-used ServiceLoader
enters the scene as a solution. It can be used to query a CustomerService
instance without knowing or accessing its implementation. Its application is shown in Listing 2, in which the main application queries CustomerService
without knowing anything about the related implementation class.
Listing 2
ServiceLoader application
01 // Create the ServiceLoader for a CustomerService 02 ServiceLoader<CustomerService> sl 03 = ServiceLoader.load(CustomerService.class); 04 05 // Use first implementation 06 CustomerService service = sl.iterator().next(); 07 08 set<Customer> customer = service.search("Tux*");
ServiceLoader
thus acts as a broker between different modules. To do so, the providing module must publish the implementation using the provides
keyword (Listing 1, line 11), and the module that is using it must publish it via uses
(Listing 3, line 7).
Listing 3
app description
01 module de.lm.java9.app { 02 // required 03 requires de.lm.java9.modulea; 04 requires logback.core; 05 requires logback.classic; 06 // uses Service 07 uses de.lm.java9.modulea.CustomerService; 08 }
Java 9 breaks down the normal run-time library into 96 small modules, such as java.core
and java.xml
. It is comparatively easy to switch your own applications to the new module concept; libraries used for this purpose do not usually need to support it immediately. Instead, it is typically fine to add the normal JARs to the module path (e.g., slf4j
or logback
). They are then available as modules in automatic mode.
Normal visibility rules from the class definition apply (private
, package
, public
). The module names each derive from the names of the JAR files. Through the use of these names, they can be used by real modules in named mode with a module description.
If you use dirty hacks like Class.forName
or load resources across JARs, you will not be able to get your application running on Java 9 without making changes. This means moving to the new strategy, or at least building a bridging module that combines the old and new worlds.
All told, the wait for Jigsaw seems to have been worthwhile. For example, the dependencies and published interfaces can now be cleanly defined and evaluated throughout the entire life cycle, from compiling through run time. Developers can force loose coupling for the first time using the ServiceLoader
mechanism and the different visibilities inside and outside a module.
The modular run-time environment itself allows for a smaller memory footprint on less powerful hardware. Class.forName
also causes comparatively little pain. The downside is the lack of support for module versions as offered by Maven. The only escape route here is to manipulate the module name as in modulea_v1
, modulea_v2
, and so on.
Buy this article as PDF
(incl. VAT)
Buy ADMIN Magazine
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Most Popular
Support Our Work
ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.