Java 6 was released in 2006 and Java 7 in 2011. No major changes were added to the Java7, many of the new features were present in Java 6 updates. After Java 7 Oracle has decided to implement a two years roadmap planning for Java, and the next major release will be available in 2013.

Java 8 has some interesting new features like lambda expressions, but the major new feature planned was Jigsaw, in fact Jigsaw was originally intended for Java 7 but was deferred to Java 8 and now it’s moved to Java 9.



Here’s a brief description from Jigsaw website of the motivations behind it:

“The original goal of Jigsaw was 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. We expected the resulting module system to be useful to developers for their own code, and it would have been fully supported for that purpose, but it was not at the outset intended to be an official part of the Java SE Platform Specification.”

When discovering the goal of Jigsaw the first question we can ask is:

Why invent another module system? The OSGi approach is not sufficient?

OSGi as described in a previous post is a mature approach used by Eclipse and it’s used by many other projects. But what’s interesting with Jigsaw is it will be integrated into the java platform, and the JRE itself as you will discover later is structured with Jigsaw modules, and maybe with Java 9 the modular approach will be mostly adopted than now.

To discover this new feature we will analyze the custom edition of Java 8 implementing Jigsaw. For this purpose JArchitect will be used to go inside the design and implementation of Jigsaw.

The standard Java 8 is structured with jars like all previous Java versions, but with Jigsaw the structure is changed. Here’s the dependency graph between packages for standard java8

The JRE is structured by using jars, and each jar contains many types, and almost all types are present in the rt.jar, this structure is not clean, and some dependency cycles exist between jars, however the JRE implementing Jigsaw is structured by using modules, and each major features are isolated to a specific module, the structure became cleaner.

Module

A module is a collection of Java types with a name, an optional version number, and a formal description of its relationships to other modules. In addition to Java types a module can include resource files, configuration files, native libraries, and native commands. A module can be cryptographically signed so that its authenticity can be validated.

The Java programming language is extended to include module declarations for the purpose of defining modules, their content, and their relationships to other modules. A compilation unit containing a module declaration is, by convention, stored in a file named module-info.java and compiled into a file named module-info.class.

And to understand better the module concept, let’s go inside the jndi module, and here’s its declaration:



module jdk.jndi @ 8-ea {

requires local jdk.auth.internal@8-ea;

requires local jdk.base.internal@8-ea;

requires optional jdk.desktop@8-ea;

requires jdk.rmi@8-ea;

requires jdk.tls.internal@8-ea;

requires optional service javax.naming.ldap.StartTlsResponse;

provides service sun.net.spi.nameservice.NameServiceDescriptor with sun.net.spi.nameservice.dns.DNSNameServiceDescriptor;

// default view exports

exports com.sun.security.auth.*;

exports com.sun.security.auth.module.*;

exports javax.naming.*;

exports javax.naming.directory.*;

exports javax.naming.event.*;

exports javax.naming.ldap.*;

exports javax.naming.spi.*; view jdk.jndi.internal {

exports com.sun.jndi.toolkit.url.*;

exports sun.net.dns.*; permits jdk.cosnaming;

permits jdk.kerberos;

}

}



Let’s discover each module section

requires

Jndi depends upon other modules, until now nothing new, the jars also depends on other ones, but what’s new is that with Jigsaw approach we specify all the modules required with their versions, and the version specified is the used one, we can also specify a range of versions.

It’s true that Maven provides also an interesting way to specify dependencies between jars, but with Jigsaw we have more control and flexibility when defining module dependencies.

If we search for all types used by jndi they must exist in the modules specified by requires section.



from t in Types where t.IsUsedBy (“jndi”)

select new { t, t.NbBCInstructions }



As we can observe all modules used are specified in the module specification.

provides

A service is a well-known set of interfaces and (usually abstract) classes. A service provider is a specific implementation of a service. The classes in a provider typically implement the interfaces and subclass the classes defined in the service itself.

A module can declare that it provides a service and specify the service provider by using the “with” keyword.

For example for jndi we have this line in its module declaration:



provides service sun.net.spi.nameservice.NameServiceDescriptor with sun.net.spi.nameservice.dns.DNSNameServiceDescriptor;



What specify that it provides the service sun.net.spi.nameservice.NameServiceDescriptor and the implementation is sun.net.spi.nameservice.dns.DNSNameServiceDescriptor.

We can search for all service providers of the sun.net.spi.nameservice.NameServiceDescriptor service:



from t in Types where t.Implement (“sun.net.spi.nameservice.NameServiceDescriptor”)

select new { t, t.NbBCInstructions }



Only sun.net.spi.nameservice.dns.DNSNameServiceDescriptor from jndi implements this service.

exports

An exports clause in a module declaration makes the public types in the package it names available to other modules, so we can with Jigsaw defines boundaries, and not all public types could be used from other modules, we must explicitly specify which types are visible.

The jndi module exports many packages, what means that only these exported types could be used from other modules.

Let’s search for all types from jndi used by other modules:



from t in Projects.WithNameIn( “jndi”).ChildTypes() where t.NbTypesUsingMe>0 && t.TypesUsingMe.Where(a=>a.ParentProject.Name!=”jndi”).Count()>0

select t



As we can observe some packages are already specified in exports clause, but what about com.sun.jndi.toolkit.url, which present inside exports clauses of the view section?

view

In large software systems it is often useful to define multiple views of the same module. One view can be declared for general use by any other module, while another provides access to internal interfaces intended only for use by a select set of closely-related modules.

For example with jndi we want that com.sun.jndi.toolkit.url be visible only for cosnaming and kerberos modules, as specified in the module declaration.



view jdk.jndi.internal {

exports com.sun.jndi.toolkit.url.*;

exports sun.net.dns.*; permits jdk.cosnaming;

permits jdk.kerberos;

}



This way we have more flexibility to define module boundaries.

And to check that only these two modules have access to com.sun.jndi.toolkit.url, let’s search for all types using this package.



from t in Types where t.IsUsing (“com.sun.jndi.toolkit.url”)

select new { t, t.NbBCInstructions }



As we can observe only cosnaming module use it because it has the permission to do it.

With Jigsaw a module could be very well specified, and maybe this new approach will remove the dependency hell between jars.

Of course we can check dependencies by using tools, for example with CQLinq we can add rules to did the same job as require, exports, provide clauses, but it’s better that it will be integrated in the JRE.

ModuleClassLoader

In the standard approach we have two class loaders:

– VM bootstrap class loader

– System class loader

However with the modular approach we have:

-VM bootstrap class loader (see later for what it does)

-One loader per one or more modules:

– A module loader is used to start an application

– Module loaders load their dependencies, e.g. java.base, that are lazily created when it loads a class.

Of course we can always define our custom loader like OSGi does to have more control on their bundles.

Here’s a dependency graph showing some types involved when loading a module.

Conclusion

When we discover the importance of the modular approach, we wonder why it was not implemented many years before? Why it’s delayed each time? And why not use the mature OSGi instead of creating a new alternative?

Maybe in the future we will have answers of all these questions, and Jigsaw will be a success in the java world.