Alan Bateman

pageicon Sunday Dec 13, 2009

Is the JDK losing its edge(s)?

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.

pageicon Wednesday Jun 10, 2009

JavaOne 2009 Slides

JavaOne 2009 is done and I managed to survive my technical sessions.

TS-4222: Asynchronous I/O Tricks and Tips, with Jean-Francois, went well and attracted more people that I had expected. The slides are here.

TS-5052: Hacking the File System with JDKTM Release 7, with Carl Quinn (Netflix), also went well. The slides are here. The session attracted a large crowd with lots of obvious nodding as we walked through the API. This is bread & butter stuff that almost all developers can relate to. Lots of questions at the end, with quite a few on the file change notification API (this surprised me as that is a relatively niche area). We had a last minute panic with this talk. The demos were setup on Carl's MacBook (actually in NetBeans running on Ubuntu in a VirtualBox). The AV guys didn't have an adapter and so, with 10 minutes to show-time, we had to move to another laptop. The end result was that we walked through the demo code rather than running it as we had rehearsed.

On the Thursday evening we had our BOF All Things I/O with JDK™ Release 7. The panel was myself, Carl, Chris, Martin Buchholz (Google), and Jessie. It's often hard to break the ice and get a BOF moving but not this time. Questions started immediately after the introductions and kept coming until we ran out of time. A lot of questions on asynchronous I/O and other networking topics.

pageicon Wednesday May 13, 2009

Monitoring direct buffers

One of the smaller features that JSR-203/NIO2 brings to JDK 7 is a management interface for monitoring the resources associated with pools of buffers. "Buffers" here means direct buffers that are allocated outside of the garbage-collected heap (by ByteBuffer.allocateDirect), and mapped buffers, created by mapping a region of a file into memory (using FileChannel.map). The management interfaces are registered with the platform MBeanServer and exposed to tools that connect to the JMX agent. This means that tools such as jconsole and VisualVM can effectively monitor the usage of these buffers. The following is a partial screen-shot of VisualVM doing just that:

The management interface is java.nio.BufferPoolMXBean and the screen-shot is of the MBean browser plugin looking at the attributes of a buffer pool named "direct", the pool for direct buffers. In this case there are 31831 direct buffers with a total capacity of 4074368 bytes. The application in this example is a rogue test called DirectBufferGCKiller2 that continuously allocates, and discards, tiny direct buffers. Due to page alignment, the memory usage is significant higher than the total capacity of the buffers; this application could be a lot more efficient if it allocated its tiny buffers by slicing a large buffer. As an aside, page alignment is something we hope to eliminate in JDK 7 (this is a topic for another day).

For those that prefer command-line tools then it is easy to hack up a tool to monitor the usage over time. MonBuffers.java is one example. It uses the Attach API to attach to a running VM and print usage information like this:

$ java -classpath .:$JAVA_HOME/lib/tools.jar MonBuffers 18051
           direct                        mapped
 Count   Capacity     Memory   Count   Capacity     Memory
 26346    3372288  219198720       0          0          0
 29296    3749888  243742720       0          0          0
 32382    4144896  269418240       0          0          0
 36957    4730496  307482240       0          0          0
 40032    5124096  333066240       0          0          0
 44848    5742336  373251840       0          0          0
 51664    6612992  429844480       0          0          0
 58698    7513344  488367360       0          0          0

The columns with "0" relate to "mapped" buffers which aren't used by this test. With a bit of effort it would be possible to develop a much slicker tool and maybe a plugin for VisualVM (hint hint).

In addition to monitoring buffer usage in a running system it is also important to be able to examine the usage postmortem (say after a crash due to exhaustion of the native heap). In this case it is easy to hack up a quick tool that uses the HotSpot Serviceability Agent to obtain this information. It might be useful to add an option to jmap to do just that.


Update (June 23, 2009). Tomas Hurka, has announced a VisualVM plugin to monitor buffer pools. It's available now at the plugin center.


« February 2010
SunMonTueWedThuFriSat
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
      
       
Today

Feeds

Search this blog

Links

Weblog menu

Today's referrers

Today's Page Hits: 237