[jsr294-modularity-eg] EG response to 294 comments

Bryan Atsatt bryan.atsatt at oracle.com
Wed Feb 13 12:30:26 EST 2008


Welcome BJ! Hope to see you soon on 277 as well.

Now on to business :^)

First, let me say that I think this JSR should focus solely on 
supporting module systems; they will be the 99% use case, and I don't 
want to complicate it for the other 1%. I'd like to step back and 
re-frame this discussion a bit in that light; I believe the current 
proposal does both too much AND not enough...


 > All points from (A) thru (M) to (Z) recognize that a type's membership
 > of a superpackage is declared by a static artifact of the Java language.
 > This is essential because it makes reasoning about membership
 > straightforward. Any compile-time module system aimed at millions of
 > programmers cannot have module membership depend on artifacts outside
 > the language or on evaluation of arbitrary code.

OSGi is living proof that this is not true.

OSGi assumes that the "module" is self-describing, and clearly does not 
depend on the language to do so; 277 could do the same. Membership could 
be as simple as deployment package containment, as it is in OSGi.

But we want to add compile-time access checks, and so, by definition, 
the language must support them in some fashion. But what do we really 
need here?

(You may recall a document I sent around prior to the official formation 
of this JSR that described "module private" semantics; I'd re-send it 
here for context but no longer have it due to a drive crash plus an IT 
dept. backup disaster.)

For both compilation and runtime we need two functions:

1. Membership: given a class and some artifact, determine its module.
2. Access: given a class, determine if it is accessible to a class in 
another module.

Exports can then be defined using only these functions: the set of all 
member classes which are accessible to other modules.

The access function seems obvious, and is inline with your suggestion 
Andreas (and my original document): a 'module' qualifier which 
translates to an access flag in the class file.

The membership function is clearly more interesting. At one extreme, we 
could add a module name declaration to each source file; the class 
itself becomes the artifact. At the other extreme we have a new 
compilation unit and artifact, which lists all class members.

But both of these are brittle, and, just as bad, both ignore the version 
problem. Given the value of module versions at runtime, shouldn't they 
be just as important during compilation?

I argued in my original document that there is a happy medium between 
these two extremes, one which supports versions during compilation 
EXACTLY as will the runtime:

The compiler must USE the runtime.

That is, module membership should be defined by an abstraction, and the 
compiler must use that abstraction. Given that pre-compiled dependencies 
exist in the form of modules, the module system itself provides that 
abstraction (ModuleDefinition) AND the access mechanism (Repository); 
the compiler must merely use them.

Ok, so this makes sense once we know the dependencies, but... how do we 
define these for the compiler? Today we give it a list of jars called a 
classpath, so it seems to make sense that we could extend this to pass 
in a list of module name/version pairs. But this is not as flexible as 
the runtime, where version ranges and other constraints can be used to 
select dependencies, nor does it allow the compiler to implement the 
membership function for the source files.

So, back to something like a "super-package.java" file, but this time 
lets support modules in a first class manner. Call it a "module.java" 
file, and have it contain:

1. A list of member *packages*, as in the current superpackage proposal.
2. A list of import declarations, exactly as required by 277.

The first enables the membership function; the second provides data for 
the compiler to call Repository methods to find dependencies.

The module file can contain any additional annotations required by 277 
(or any other module system). The binary form can then be used by a tool 
to package up a .jam file (or an OSGi bundle with a bit more work).

At runtime, the module system binds each class to a Module by passing 
the Module instance on the ClassLoader.defineClass() invocation.

This model does not require that the .class files contain module name 
declarations, nor does it require a separate runtime binary solely for 
the JVM's consumption. Either or both could certainly be added, if this 
EG felt strongly that an extra level of membership enforcement is called 
for. I believe that the module packaging is sufficient to define 
membership, but others may disagree.

And it doesn't required nesting, the complications of which I don't 
believe are worth the benefit.

// Bryan




More information about the jsr294-modularity-eg mailing list