Featured in
Architecture & Design

Mini-talks: The Machine Intelligence Landscape: A Venture Capital Perspective by David Beyer. The future of global, trustless transactions on the largest graph: blockchain by Olaf Carlson-Wee. Algorithms for Anti-Money Laundering by Richard Minerich.

Featured in
Operations & Infrastructure

Mini-talks: The Machine Intelligence Landscape: A Venture Capital Perspective by David Beyer. The future of global, trustless transactions on the largest graph: blockchain by Olaf Carlson-Wee. Algorithms for Anti-Money Laundering by Richard Minerich.

Featured in
Enterprise Architecture

Mini-talks: The Machine Intelligence Landscape: A Venture Capital Perspective by David Beyer. The future of global, trustless transactions on the largest graph: blockchain by Olaf Carlson-Wee. Algorithms for Anti-Money Laundering by Richard Minerich.

Jigsaw has been a long-running project, first known as JSR 277 and later JSR 294, that aimed to decouple Java's core runtime library into different modules. This would allow, for the first time, a JVM to run without AWT support being required for a full server-side JVM.

Modularising the JDK itself is no easy feat; for example, the java.beans package has a dependency on java.applet which depends on java.awt; unpicking such dependencies long after the design decisions were made is tricky at best.

There has been a module system available for Java from the early days, known as JSR 8 and more recently as OSGi and JSR 291, that is used by all major Java EE application servers, and many other systems and applications in wide use today (JIRA, Eclipse) as well as specific vertical markets (embedded systems, home automation). Jigsaw follows in the footsteps of design successes such as java.util.Date, Java IONIONIO2 NIO2.2 and the java.logging package, and aims to ignore best practices to developer an inferior system for use by the JDK itself. (Fortunately, Java 8 brings the Joda time package, now known as java.time, as a fix for the fix for java.util.Date monstrosity.)

Each time 277/Jigsaw has been rebooted, the scope has been trimmed. Initially it was a generic module system for any application, along with a resolution chain and repository storage mechanism. (Since this is Java, each of these would be pluggable leading to a ModuleFactory and a ModuleResolverFactory.) Almost five years ago, in November 2008, JSR 277 was looking like a dead duck. The scope was revisited, and the idea of super-packages was put forward (leading to JSR 294) which would be a way of aggregating several packages together whilst exposing a single package or API to the outside world.

When JSR 294 faltered, the Jigsaw project was born, as a way of providing a module system primarily aimed at the JVM itself (though with an eye to allowing other applications to use it as well). Jigsaw dropped some of the more obvious features, such as the module resolver chain, and aimed to provide the basics for defining modules in Java. One key mistake in the Jigsaw proposal was allowing modules to express dependencies not declaratively, but by virtue of executing code – thus denying the possibility of doing static analysis to know whether the module system would work or not. (A module system which cannot verify if the constraints are met statically is known as the 'classpath', which is what Java developers typically use today for smaller Java applications and IDEs.)

Just over a year ago, Mark announced that Jigsaw would miss the Java 8 train, in a post Project Jigsaw: Late for the Train. Opinions were mixed on this news, with supporters and opponents of OSGi claiming it as a victory or defeat respectively; but by deferring the solution for Jigsaw until Java 9, the right decisions can be made to fix Jigsaw's problems.

With the reboot, Mark hopes to provide a prototype that doesn't stretch too far, allowing existing resolution agents to provide the JARs but provide a means to create static module dependencies between elements. At the moment, the code is just a fork of JDK8 and doesn't carry over the baggage that it had before, but to revisit some of the design decisions that caused the problems in the previous attempts.

Among other things, we're going to see whether we can get away without introducing a distinct "module mode" as we have in the current prototype (which is incompatible, in some narrow yet deep ways, with long-standing behavior) and without doing dependence resolution (since build tools like Maven, Ivy, and Gradle already do that well enough).

As we work on this new prototype we'll take code from the old one where that makes sense, but we'll also take the opportunity to question earlier design decisions and generally clean things up.

Whether the module system will express its dependencies declaratively (like Ivy, Maven and Gradle) or whether it will require code to execute to determine dependencies (this preventing static analysis and ahead-of-time verification)

Whether the module system will be dynamic (like OSGi) or static (like Maven); in other words, can modules come and go or just come

Whether the dependency metadata is represented in .class files which are understandable by the JVM or in a text format such as JSON, YAML or Manifest.MF

With Oracle's aversion to externally developed solutions, it's unlikely that OSGi will be chosen as a basis for the Jigsaw work. However, OSGi as a fully dynamic solution is overkill for modularising the JVM; an OSGi-like system with versioned dependencies and bundles but without the dynamic nature (and therefore multiple classloaders) would be an ideal half-way point between the two. The pojosr project has shown this can be done in Java already, and perhaps that would be the best of all worlds.

InfoQ will be following the rebooted Jigsaw project closely, and report on its progress.

The Ceylon module system does this pretty well, as the Ceylon language allows declarative syntax and a module.ceylon file describes the module dependencies. Also, classes, functions, values and even packages can be marked as shared (or leave out the shared keyword) allowing you to expose an API that is a well-defined subset of your functions/classes/values.