The story so far The JDK is big—and so we ought to modularize it. Doing so would allow us to improve the key performance metrics of download size, startup time, and memory footprint.
Java libraries and applications can also benefit from modularization. Truly modular Java components could leverage the performance-improvement techniques applicable to the JDK itself, and also be easy to publish as familiar native packages for many operating systems.
Connecting the dots Given a modularized JDK and a modularized application, the next logical step is to arrange for the application’s modules to declare dependences upon just the JDK modules that it requires.
This would enable a capable native package manager such as rpm or apt to download and install just the JDK modules that are needed to run the application.
This would also enable a next-generation Java Kernel to download, initially, just the application and JDK modules needed to start the application. Once the application has started up then the Kernel would download additional modules on demand, as they’re requested by the program; in the meantime it would trickle-download all the remaining modules in the background.
JDK != Java Platform The problem with this scenario is that it would leave applications, and any libraries upon which they depend, tightly bound to the JDK and hence not portable in the sense of the “write once, run anywhere” ideal. The JDK is, after all, just one implementation among many of the Java SE Platform.
Omitting some dots Small devices are becoming faster all the time, with many of them now quite capable of running a HotSpot virtual machine and the core classes of the JDK. Their persistent-storage capacities, however, are growing at a slower rate.
Manufacturers of embedded devices and high-end cell phones generally aren’t willing to increase the cost of a product in order to pay for the memory required to carry around libraries that are never actually used by applications. With a modular JDK they’d have the option of carrying just the modules that will be used by expected applications, and with modular applications they’d be able to verify, at either build or install time, the availability of the necessary JDK modules.
The monolithic Java Platform The further problem with this second scenario is that no proper subset of a modular JDK is an implementation of the Java SE Platform, since the Platform itself is monolithic and indivisible. Put another way, no such subset can be tested for conformance against any particular Java SE Platform Specification, since the Specification itself is monolithic and indivisible.
Meta-modularization By now the solution to the above two problems is, no doubt, obvious: The Java SE Platform should be modularized.
This process could start with the definition of an abstract “Java SE” module whose version number would be that of the Java SE Platform Specification that defines it. The content of that specification would, as usual, be determined by the Expert Group for the corresponding Java SE Platform JSR under the auspices of the Java Community Process.
The primary module of the JDK—which would presumably be an aggregation of the concrete modules comprising the JDK—could then be amended to declare that it implements the Java SE module, much as a Java class can declare that it implements an interface. Similar adjustments could be made to other Platform implementations.
Once this is done then a modularized application could declare that it depends upon a specific version of the SE Platform—but not upon any particular implementation thereof. At runtime it would be up to the underlying module system to locate a Platform implementation capable of fulfilling this abstract requirement.
Divide and conquer To finish addressing the two problems described above, the next version of the Java SE Platform Specification could define specific common subsets—or Profiles—of the Platform. There could be, e.g., Profiles for minimal headless applications, for simple RIA-style desktop applications, for richer desktop applications, for server applications, and for other configurations at various points in between. The Java Compatibility Kit would correspondingly be divided into subsets of tests for each Profile.
Each Profile would be represented by its own abstract module. For each of the Profiles that it supports, a conforming implementation of the Platform would be required to include a concrete module that implements the corresponding abstract module.
Once all this is done then a modularized application could declare that it depends upon a specific versioned Profile of the Platform. An application delivered as familiar native packages, or via a Java-Kernel-like mechanism, would no longer be bound to any particular Platform implementation. A small device, finally, could include just the subsets of the Platform that are required by the applications expected to run upon it—yet still claim conformance to the Platform Specification.
Now wouldn’t that be truly and completely cool?
The only remaining question is: How do we get there?