Module-system requirements

mark.reinhold at oracle.com mark.reinhold at oracle.com
Mon Mar 9 20:56:17 UTC 2015


2015/2/15 10:12 -0800, Tim Boudreau <niftiness at gmail.com>:
> mark.reinhold at oracle.com:
>> As I wrote in my reply to David, I think resources (in the traditional
>> ClassLoader::getResource sense) should be treated as being strictly
>> internal to modules.  ...
> 
> There's a common case that I'd like to understand how you solve without at
> least META-INF or its equivalent visible to other modules:  It's fairly
> common to see applications that dynamically compose things they find on the
> classpath.  Spring and a few other things accomplish this through
> classpath-scanning, which is a fairly horrible pattern (you can wind up
> visiting every class on the classpath, or a large subset, just to look for
> a runtime annotation that is not there for the vast majority).
> 
> An alternative approach I've used many times, which I think a few
> frameworks do as well (dagger?) is:  Write an annotation processor that
> generates a flat file in META-INF that lists the classes that have the
> annotation in question;  runtime code loads all such files on the classpath
> and uses that to initialize things that should be present at runtime.  It's
> really the same pattern as ServiceLoader.
> 
> Is it safe to assume that, whatever happens, that approach will still work,
> whether by special-casing META-INF/** or some equivalent?

For JAR files on the legacy class path that approach will, of course,
continue to work.

I don't expect actual modules to be on the class path (about which more
below), which raises a question: Will a framework such as Spring need to
discover the classes bearing certain annotations in modules that aren't
yet configured and loaded, or in loaded modules, or both?  In the former
case it would inspect module artifacts, while in the latter it would
inspect some reflective run-time representation of a loaded module, since
the original module artifact might not be available.

Either way, this use case suggests a new requirement for the Development
section:

  - _Annotation digests_ --- When packaging a module into an artifact it
    must be possible to augment its definition with a summary of all of
    the type- and package-level annotations that are present in the
    module, together with an indication of the types and packages to
    which each annotation applies.  This digest must be easily readable
    from module artifacts, and at run time those parts of it related to
    annotations retained for run time must be available through an
    appropriate reflective API.

Comments?

>> Having said that, I do agree that the module system must provide some
>> kind of escape hatch or "promiscuous mode", as you call it, so here's
>> a stab at an additional requirement for the "Modularizing Java SE"
>> section:
>> 
>> - _Overrideable encapsulation_ --- It must be possible to force a
>> module to export one or more of its packages to all other modules,
>> or to some specific modules, even if its definition does not do so.
> 
> One sort of low-hanging-fruit approach to this would be:
>  - Modules do not use the traditional $CLASSPATH
>  - The contents of $CLASSPATH are treated by the system as a single module
> (so everything can see each other, and legacy code behaves as expected)

That's looking ahead to a design decision, I think, but in fact the
approach I intend to propose treats the legacy class path as the content
of a special "unnamed" module, analogous to the unnamed package, which
implicitly depends upon all other modules so that it works essentially
as you describe.

- Mark


More information about the jpms-spec-experts mailing list