harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Richard S. Hall" <he...@ungoverned.org>
Subject [modules] Packaging Class Libraries
Date Thu, 09 Jun 2005 08:21:39 GMT
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
>>>
>>>
>>>
>>
>>
>

Mime
View raw message