Exporting things (Was: Re: Module-system requirements)

mark.reinhold at oracle.com mark.reinhold at oracle.com
Mon Mar 9 21:00:17 UTC 2015


2015/2/20 6:33 -0800, david.lloyd at redhat.com:
> On 02/16/2015 07:15 AM, David M. Lloyd wrote:
>> ...
>> 
>> What you are saying here implies (to me) inspecting the call stack to
>> ensure that the caller actually exists within the module being
>> referenced.  I'm not certain we really want to go this far, if my
>> interpretation is accurate.  Such a rule is reasonable on the face of
>> it, but it does more or less break all the code in existence which
>> currently uses resources as a sort of API into a library, and this
>> includes very common patterns for loading configuration (among many
>> other things).
> 
> Going into a little more detail on this, I picture a number of scenarios:
> 
> 1) A resource is fully internal to a module, and there's no reason that 
> any external code ought to need or get access to this data.  The module 
> could restrict access to the resource by caller as inferred above.
> 
> 2) A resource is an internal part of the module, but other things might 
> need access to the resource for specific purposes (like direct .class 
> access for instrumentation).  The access restriction of this use case is 
> "solved" by existing containers today by isolating class loaders, so the 
> user has to have access to the target class loader in order to read the 
> resource(s) in question.  You could subdivide this into (2a) the .class 
> files themselves and (2b) anything else that might fall under this 
> category, as I believe the use cases for (2a) are fairly specific to 
> run-time analysis and instrumentation tooling and similar uses.
> 
> 3) A resource is a part of the module's self-configuration, but is not 
> of interest to importers.  This would include configuration files (like 
> Java EE deployment descriptors, and other framework-XML-ish things). 
> Access is typically presently solved similarly to #2 above, or by simply 
> accessing the target resource archive directly, bypassing class loading.
> 
> 4) A resource is a part of a public API intended to be imported and used 
> by consumers.  Examples include framework configurations like logging 
> and some other framework-XML-ish things, ServiceLoader, etc.  Today this 
> is solved as an unavoidable consequence of flat classpaths, but also (in 
> containers) by implicitly or explicitly exporting and importing some or 
> all of a class loader's resource file/directory structure.

I think cases (2) and (3) are supported by the requirement I suggested in
my previous reply, which allows suitably-privileged code to read class
and resource files from a module's defining artifact.

As to (4), I wonder if it's really all that different from (3).  If a
logging framework, e.g., is invoked by some module and then needs to read
that module's logging-configuration file then can't it just read it out
of the module's artifact?  (I suspect it's reasonable to assume that a
logging framework will have the permissions required to do so.)

> While JBoss Modules does in fact solve cases 2-4 well enough, there is 
> no provision for things falling under (1).  This is not however due to 
> any fundamental ideal; quite the opposite in fact.  I simply could not 
> work out a consistent (and simple) set of rules for treating classes and 
> packages separately from resources and their directories that didn't 
> simply break everything*.
> 
> The questions are: Are there yet more use cases that I have failed to 
> identify?  Is it possible to come up with a consistent set of rules 
> which allows all these primary use cases to continue to function cleanly 
> going forward?  Can we do so in a minimally-impacting manner that would 
> allow most existing code to continue to function with (at most) only 
> packaging changes?  If not, which use cases can or should be sacrificed, 
> and why?

If you can read class files and resources from a module's artifact then
existing components that publish information in that way can continue to
do so.  Components that read such information will require some minor
changes, since the ClassLoader::getResource* methods might not work for a
module in the way that it does for the class path, or might work slowly,
but this change should be fairly simple, e.g., going from

    object.getClass().getClassLoader().getResourceAsStream("foo")

to something like

    object.getClass().getModule().getModuleArtifact().getStream("foo")

In return for mandating (or strongly suggesting) this minor change in
resource consumers we get resource encapsulation, and we can also avoid
having a complicated "exports resources" feature.  That seems like a
worthwhile tradeoff.

> I could easily imagine adding a separate public resources concept which 
> is wholly separate from the module internal content, where importers 
> could import some or all of these resources into their own world, which 
> would easily solve (4), but (2) and (3) are still left "high and dry". 
> An "unexported resources" area of a module could address (3), leaving 
> (2), which could be solved by co-locating those resources with the 
> classes themselves.  But by this point there is some additional 
> complexity (maybe not *too* much, but definitely some).

Yes, this is getting rather hairy ...

>                                                          Module imports 
> would specify the module they want to import (possibly to package 
> granularity), as well as the resource directories they want to import 
> (which could be re-exported just like module packages could).  So from 
> that perspective the additional complexity is manageable.  But when it 
> comes to build and packaging of a module itself, users would now have 
> face possibly fairly complex decision regarding which category a 
> resource belongs to (not to mention that packaging tooling would have to 
> support this decision),

I agree that this seems like too much.

>                         whereas in today's world they just "throw it in 
> there" and hope for the best.

Well, hopefully we can do better than that!

- Mark


More information about the jpms-spec-observers mailing list