Coupling modules and class loaders

David M. Lloyd david.lloyd at redhat.com
Thu Dec 10 15:39:28 UTC 2015


On 12/09/2015 07:27 PM, mark.reinhold at oracle.com wrote:
> 2015/10/21 3:53 -0700, david.lloyd at redhat.com:
>> ...
>>
>> I propose that modules are best defined as a specialization of class
>> loaders.  Class loaders already have many of the properties that define
>> a module: encapsulation, isolation, unique identity for packages.  In
>> fact OSGi already uses this unit.  The only thing they are really
>> missing is the ability to use a graph-like dependency structure, hence
>> the specialization.
>
> Class loaders do not provide strong encapsulation.  How do you propose to
> extend them to do so?

Sure they do - here are some ways:

* Package-private and protected members in one class loader are 
inaccessible to packages in another class loader, even if the package 
has the same name.
* Run-time linkage is strongly encapsulated by class loader boundary; I 
can declare a public type that nevertheless cannot be linked against by 
anyone, if the class loader denies such access.  There are several use 
cases for this.

If I could extend this in any in any way, I would do two things (whether 
or not modularity goes forward in the platform):

1) Expand the default access level to be class loader private (and 
similarly change protected), which would give users a means to define a 
type and members which are accessible to the module but inaccessible 
outside of it, while still allowing universal access to public types. 
Specifically this would apply only when referencing types in a Java 9 
class file.  References to types in Java 8 (and earlier) class files 
would still use the package as the protection level (though I doubt this 
distinction would ever come up in practice as few artifacts have a mix 
of class file versions within them).

2) Add a single method to the class loader which would allow (at package 
definition time) a package to be declared to be accessible from specific 
other parties (probably other class loader+package combinations).  This 
information would theoretically be utilized by the bytecode verifier to 
restrict access in the same manner that package-private access is 
restricted today.  This solves the old "friend module" case from JSR 
294, though I recall that there wasn't agreement as to whether it was 
necessary (it would certainly eliminate the need for the "shared 
secrets" mechanism though).

The corresponding functionality at build time would amount to telling 
javac where to find each dependency, and possibly also telling javac 
which dependency packages are expected to be accessible at run time (if 
#2 above would be implemented, which would not strictly be necessary IMO 
but might be a good feature to have).

>> ...
>>
>> What is the justification for the more complex Jigsaw approach?
>
> One developer's complexity is another's simplicity.

Fair enough, that was definitely a subjective assessment.

> The primary motivation is, as Rémi noted, to make it easy for existing
> applications that use class loaders in sophisticated (and sometimes very
> strange) ways to adopt modules.  If the maintainers of such applications
> must make deep changes to their class-loading architectures in order to
> support modules then some of them simply won't bother.

I don't think they would though.  Even in the complete compatibility 
case, the "flat classpath" module could and would still just be one 
module with the whole class path on it, which would be not unlike Ye 
Olde Application Class Loader, while still allowing the forward 
migration path of adding real module dependencies to the ugly legacy 
class path.  Running with -jar gives us two options: compile a flat 
classpath as above, or assemble a module graph (with a variety of 
transitivity possibilities) based on Class-Path references.  Even the 
legacy extensions thing works surprisingly well as a module system, if a 
somewhat primitive one, had it not been deprecated (removed?) from the 
platform in SE 9.  If people are doing weird/nasty/ugly stuff with class 
loaders, they would certainly be free to continue to do so if they want; 
the per-class loader idea does not necessarily require that the module 
class loader class be final, nor does it forbid it from being used as a 
parent or delegate, unless you're thinking of something else?

> The fact that OSGi and JBoss have successfully used class loaders to
> implement module systems that are capable of loading a wide variety of
> existing artifacts is interesting.  It does not, however, imply that all
> existing applications can be converted to use the class-loader-per-module
> approach, nor that they should be forced to do so.  The proposed design
> therefore neither mandates nor forbids that approach.

I think we probably would not be able to put bounds on this without 
enumerating specific use cases/behaviors (especially those that would 
fail in this situation but not in the other), as I haven't encountered 
nor been able to imagine a situation that would fail solely due to the 
introduction of class loader based modules.

-- 
- DML


More information about the jpms-spec-experts mailing list