Geir Magnusson Jr. wrote:

Heh. I agree. I just was too busy in the VM/class library fire- fight :)


Yes, perhaps you have just signed the death notice for this discussion too. ;-)

So, given that my foray into architecture discussion was such a stunning success, would you like to start the discussion of such a thing might be approached? (Please change the subject, of course...)


We can try.

I have to admit up front that I know nothing about implementing a VM, but I do have some knowledge about class loaders, having worked on an OSGi framework implementation for a few years.

My view of the OSGi framework is that it really serves as a nice, dynamic module layer for Java in general and its service-oriented approach is a good way to structure applications. This has been my approach to using/evangelizing the OSGi framework since I started with it back in 2000. I recognize that the "dynamic" and "service-oriented" parts of the OSGi framework are probably of little relevance to a JVM implementation, so I will try not to discuss them.

However, having said that, I do think that the dynamic aspects could be very interesting, because they would allow the JVM to dynamically deploy and update modules as needed. That is all I will say about dynamics, I promise. :-)

My view on packaging class libraries is rather simplistic, but it has worked for many OSGi users. The approach is to package libraries into JAR files, where the JAR file is an explicit module boundary. Each module has metadata describing the packages it exports and imports (and version information). A module JAR file may include classes, resources, and native code.

Module JAR files are not directly made available via something like the CLASSPATH, instead the module system reads the metadata for each module (i.e., its export and import information) and resolves a given module's imports to the available exports from other modules. A class loader is created for each module and the module class loaders form a graph, where edges represent an import-to-export resolution.

All classes of a given module are loaded by its own class loader. Any classes from an imported package are loaded from the class loader of the module that exports that package and to which the import was resolved. In this fashion, the class delegation pattern among modules is a graph, not a hierarchy...although the concept of a hierarchy of class loaders still exists since it is built into the ClassLoader class.

Depending on how you wanted to implement the module system, you could make the module containing the "java.*" packages special in the sense that its class loader is the parent of all other module class loaders and that modules do not need to explicitly import from it (which is the approach used by OSGi). However, there is still possibly value in requiring that modules do import those packages for version resolution purposes.

As an example of all of this, consider this fictitious metadata for packaging some libraries as modules (these example will not include all of the real packages to keep things short):

Module-Name: Core
Export-Package: java.lang; exclude:="VM*"; version=1.5.0,
   java.io; java.util; version=1.5.0
Native-Code: lib/libfoo.so; // I won't go into any syntax here :-)

This module is the core Java class library. It exports "java.lang", but excludes exporting any classes from it whose name starts with "VM". The "VM*" classes will be visible inside the module, but not to modules that import "java.lang". Of course, excluding these classes wouldn't be necessary if the "VM*" classes were package private. However, this features allows you to make them public if you want. Another approach that would be enabled is to just move the "VM*" classes to a different package and make them public and simply not export that package, which won't allow other modules to access them either.

[A side note about the syntax above: The syntax differentiates between framework directives using the ":=" token, versus importer matching attributes using the "=" token. Matching attributes are used by importers to select exporters; see next example.]

Continuing with two more simple module examples:

Module-Name: OMG CORBA
Export-Package: org.omg.CORBA; org.omg.CORBA.portable; \
   version=1.5.0

Module-Name: Javax RMI
Export-Package: javax.rmi; javax.rmi.CORBA \
   version=1.5.0
Import-Package: org.omg.CORBA; org.omg.CORBA.portable; \
   version="[1.5.0,1.6.0)"

The first module exports the CORBA packages, whereas the second one imports the CORBA packages and exports the javax.rmi packages. The import for the CORBA packages specifies a matching version range of 1.5.0<=x<1.6.0, under the assumption that micro version number changes are backwards compatible.

Assuming that all of the various libraries are packaged up using similar metadata, then you can imagine a simple approach where all of the modules are placed into some directory and when the module system starts, it scans the directory and does a consistency check and makes sure it can successfully resolve all imports to exports, etc.

For backwards compatibility, a "system class loader" could be created that delegated to all of the module class loaders, to get the current boot class path type of approach. The application class loader would then have this "system class loader" as its parent, so it could access everything on the boot class path, as expected.

I admit that I have not given as much thought to this very last part, since the OSGi framework doesn't have to do such stuff, but at first blush it seems reasonable. Even then, it would still be nice if somehow this module layer could be exposed, so that applications could be written with it in mind if they so desired.

All of the above stuff (and more) is basically functioning in some form in my current alpha release of Oscar 2.0:

   http://oscar.objectweb.org/oscar-alpha.html

I await the list's wrath.  :-)

-> richard



geir

On Jun 8, 2005, at 3:01 PM, Richard S. Hall wrote:

Apparently, only you and I agree.  ;-)

Dalibor Topic wrote:


Richard S. Hall wrote:


To me, this is the point. I would like to see all of the libraries built on to of the JVM to be packaged in a more module- like fashion, so that their exports and imports are explicit. There would be many benefits if this were done, rather than relying on the current approach of assuming that everything is accessible.



+1


So, from my point of view, it is definitely going in the right direction to make libraries understand which class loader they should use to get to their own "module's" classes, as opposed to just assuming they can get them from any application class loader.



+1 to that, too.

cheers,
dalibor topic






Reply via email to