Oracle's Java Platform Group chief architect Mark Reinhold has published a report on the State of the Module System, with an emphasis on what the modularization objectives are (and aren’t.) The publication has triggered comments among users due to the apparent overlap with existing frameworks, particularly OSGi.

As explained in the report, and fully detailed in JSR-376 and in the Module System project page, the module system is meant to address two omissions in the current Java accessibility model:

Reliable configuration: the current way components access classes from other components through the class path is considerably error-prone, particularly when attempting to use classes that aren’t in the class path or that are present multiple times.

Strong encapsulation: there is no way to restrict the classes that a particular component exposes to other components, every class categorised as public will be accessible from outside.

Full details can be found both in the report and in previous InfoQ articles, but to summarize, each component is typically (but not necessarily) represented by a jar file, which includes a module descriptor file called module-info.java with the following structure:

module com.foo.bar { requires com.foo.baz; exports com.foo.bar.alpha; exports com.foo.bar.beta; }

The file is structured such that one or more lines of exports will indicate the packages that are to be accessible from other components, and where zero or more lines of requires will indicate the modules that are required by this module. This system provides a method for assessing at compile time whether the access types have the right visibility (i.e. they are public and exported by the required component), and at run time to assess whether the necessary modules are available, without having to inspect the full class path. It is here where the similarities with OSGi are manifest.

OSGi Background

OSGi is a modularization system and service platform for Java that implements a complete and dynamic component model. First proposed in 1998 with JSR-8 and with subsequent reviews being published over time (the last in 2014), OSGi allows the definition of bundles (akin to modules), which take the form of a JAR file with the following MANIFEST.MF file:

Bundle-Name: Hello World Bundle-SymbolicName: org.wikipedia.helloworld Bundle-Description: A Hello World bundle Bundle-ManifestVersion: 2 Bundle-Version: 1.0.0 Bundle-Activator: org.wikipedia.Activator Export-Package: org.wikipedia.helloworld;version="1.0.0" Import-Package: org.osgi.framework;version="1.3.0"

(Sample taken from Wikipedia.)

It is apparent that in spite of the format differences, the intent expressed is similar to the Java Platform Module System. Indeed, the similarities between the Java Platform Module System and OSGi have been noticed since the initial attempts to modularise Java started in 2005 with JSR-277, the “Java Module System”. Initially aiming at Java 7, JSR-277 focused on easing distribution and execution of Java artefacts. Despite having a nearly identical name to JSR-376, that initiative had slightly different objectives; although it was tasked to fix the problem of "reliable configuration", it did not attempt to tackle the issue of "strong encapsulation". And in contrast to JSR-376, it also tried to add a versioning model to the Java artefacts. The similarities between these objectives and the functionality provide by OSGi were stark enough for the authors to initially consider OSGi as a solution, later discarding it reasoning that OSGi version control was too weak.

JSR-294 was created shortly after that, with the objective of implementing “Improved Modularity Support in the Java Programming Language”. Also aiming at Java 7, this JSR was created to add the concepts of modules (called “superpackages”) to fix the strong encapsulation problem; this concept aligns with the current Java Platform Module System project. Both JSR-277 and JSR-294 have been dormant ever since they were labeled as such in 2012, when the Java 7 target was dropped, and are superseded by JSR-376.

Another link between OSGi and the modularisation of Java can be found in JSR-291, "Dynamic Component Support for Java SE" (essentially an implementation for OSGi Service Platform Release 4). That JSR made a reference to JSR-277, the original Java Module System, to clarify the difference in scope of both initiatives: JSR-277 would focus on the static module definition to be used by Java, while JSR-291 focused on dynamic components that can be loaded and unloaded on runtime.

Finally, JSR-376 itself also makes a reference to OSGi, mainly to discard it as a valid solution because its scope was far greater than the Java Framework Module System spec.

Given all the above, it seems reasonable that a number of users would have difficulty differentiating the new Module System and OSGi. However, the conclusion is that the module system and OSGi are understood to be complementary systems serving different purposes, with OSGi being a framework built on top of Java to create an environment where bundles can be managed dynamically in an always-running application, and the module system being a new capability of Java itself that allows for tighter and easier control of statically managed modules.

Differences between Java Platform Module System and OSGi

To understand this a bit better, InfoQ talked to Holly Cummins, co-author of Enterprise OSGi in Action. While the following doesn’t intend to be a thorough description of the differences between the Java Platform Module System and OSGi, it provides the reader with a basic understanding of how different their objectives are.

On one hand, the new Module System in Java will provide an easy way to check visibility of packages and classes at compile time, however, when we asked whether OSGi’s bundles can be used in the same way, Holly declared that “the answer for this is surprisingly complex”.

OSGi dependencies are expressed in a bundle’s manifest, and there are two basic approaches to creating the manifest: "code-first" and "manifest-first". With the code-first approach (used in the bnd tool, and the maven bundle plugin), the list of dependencies isn't enforced at compile-time, it's actually generated at compile time. The compilation goes ahead in the usual way, and then the tooling works out what's needed at runtime based on what was needed at compile time. The alternate approach is manifest-first, which is used by the Eclipse PDE tooling. In this approach, dependencies are declared in the manifest, and the Eclipse IDE will use the manifest to work out what classes your code can see, and highlight cases where a dependency is missing. There's a PDE command-line build, and a Maven plugin called Tycho, and both of those enforce the dependencies at compile-time. However, it’s important to note that this visibility isn’t enforced by OSGi itself but by the tools accompanying PDE; since not all teams using PDE use one of those tools, and there's a possibility to miss a trick at compile-time.

Another key aspect of the new Module System is the ability to restrict the modules that a particular package is exposed to, useful in situations where a set of related modules need to access each other, but they shouldn’t be accessed beyond that. As indicated in Mark Reinhold’s report, this can be achieved using the following syntax:

module java.base { ... exports sun.reflect to java.corba, java.logging, java.sql, java.sql.rowset, jdk.scripting.nashorn; }

OSGi didn’t initially have this capability, but when it was added it again went further than the objectives of the Module System. As Holly explains, “Any bundle can register a resolver hook, and that can be used to filter matches, so that packages are only exposed to specific bundles. You could use the same mechanism to do things as sensible as exposing packages to bundles which declare certain metadata, or as crazy as exposing a package only on Tuesdays”.