Is the JDK losing its edge(s)?
By user12820862 on Dec 12, 2009
One of the goals for JDK 7 is to get us to a modular platform. Getting there will be hard as it's a very interconnected code base with many undesirable dependencies between APIs and different areas of the implementation. These dependencies have built up over many years and releases. To give an example (from a couple of builds ago but mostly applicable to JDK 6 too): Suppose you are using the Logging API (meaning java.util.logging). Logging requires NIO (for file locking) and JMX (as loggers are managed). JMX requires JavaBeans, JNDI, RMI and CORBA (the JMX remote API mandates that the RMI connector support both JRMP and IIOP). JNDI requires java.applet.Applet (huh?) and JavaBeans has dependencies on AWT, Swing, and all things client. Not satisfied with this, JavaBeans has persistent delegates that create dependencies on JDBC and more. I could continue but it should be clear that this seemingly innocent use of the logging API results in transitive dependencies that envelop almost the entire platform. And just to be clear - these are just dependencies and logging shouldn't of course require any of CORBA's 1600+ classes to be actually be loaded. Think of it more like dinner for two except that she hires a fleet of buses to bring her extended family and friends to wait outside the restaurant.
The good news is that we've started to make progress over the last few builds to address many of these issues. Logging no longer requires JMX (this required an API change to be backed-out/re-visited). We're separated out the RMI-IIOP transport so you can do remote management without CORBA being present. JMX will now do its own introspection when JavaBeans is not present. JNDI no longer requires java.applet.Applet, JavaBeans no longer requires JDBC, AWT no longer requires RMI, and many more.
So where are we at? At this time we have a tentative base module that is essentially the core libraries (think lang/io/net/util/nio/security). The dependencies that used to exist from the classes in this module on JNDI, deployment code, AWT, the preferences and logging APIs, and JMX have been removed or inverted. There is a remaining dependency on XML parsing (from java.util.Properties) and that will be solved in time.
All things Swing, AWT, 2D, etc. are grouped into a tentative client module. The APIs in this module are deeply interconnected and so pose a big challenge. There are still a few dependencies from other modules (like web services) on client that will require work but ultimately it should be possible to chop off the head, say when deploying on an embedded device.
We have a several fine-grain modules that could potentially be grouped, maybe into coarser grain profiles in the future. Logging, RMI, JSSE (SSL), SASL, JDBC, JNDI, LDAP and other JNDI providers, PKCS11 and other security providers to name some of them. JSSE is a good example of work done to decouple it from other areas of the platform. One would think it should be possible to do secure networking without requiring the world but, as SSL can negotiate to use Kerberos based authentication, it was tied to Kerberos/JGSS. For this case, the dependency is now optional. If Kerberos is installed then SSL will include the Kerberos cipher suites when negotiating the security context. When not installed it won't negotiate to use Kerberos.
I mentioned CORBA above as it is often used as the whipping boy by those that are critical of the compatibility baggage that the JDK carries. A potential module that has been suggested is a compatibility module for deprecated, legacy, unloved and other baggage. Good work from Sean Mullan and Vincent Ryan in jdk7 b78 removes the dependencies on the deprecated security classes so that they don't need to be in the base module. Other potential candidates are the legacy sun.io converters. We should have ditched these years ago but there are still JDBC drivers that haven't removed their dependencies. We've also got many classes in sun.misc that aren't used anymore but we can't remove them because there may be naughty applications out there using them directly. Legacy protocol handlers and content handlers are other candidates. I'm sure the reader can think of others.
In the above it is worth pointing out that modules aren't necessarily aligned on package boundaries. It's clearly desirable for a module to contain all the classes that are in one or more complete packages but there are many cases where this isn't not possible. I mentioned JavaBeans above and that is a clear case where one has to separate out the property event support and annotations from the introspection and other classes that tie one to the client area. APIs such New I/O and Logging have management interfaces and it makes a lot more sense to group the management interfaces into the management module along with with JMX and java.lang.management. I mentioned the separation of the IIOP transport from the RMI Connector above. For that one, the rmic compiler will generate the stubs and ties to the javax.management.remote.rmi package but we wouldn't want to group these into the management module as it would create a dependency on CORBA. If one were to split up the base module further then it would mean looking at packages such as java.util that contains a lot more than the collection APIs.
I hope the above gives you a feel for the work that has been happening in jdk7. A more modular JDK should get us closer to our goals to improve performance (download and startup time), enable the platform to scale-down, and more. For those interested in diving into this further then the Jigsaw project page and mailing list are a good starting point. The jigsaw/tools repository has the ClassAnalyzer tool that we've been using to analyze dependencies and guide the changes. The tool consumes module definitions and generates several files per module, including the list of classes, and dependencies. There are summary files in various forms, including DOT files for those interested in visualizing the dependencies. Much of the work mentioned above can be thought of as removing edges from the dependency graph. Mandy has been working on the next step, the build changes so that the JDK build will generate modules rather than rt.jar. This will take a few steps to get there. Initially the build will generate JAR files but ultimately we will of course transition to a better container format.