Proposal: #NonHierarchicalLayers

mark.reinhold at mark.reinhold at
Thu Jan 26 22:34:31 UTC 2017

2016/12/13 6:47:53 -0800, david.lloyd at
> On 12/12/2016 05:23 PM, mark.reinhold at wrote:
>> 2016/12/8 5:46:24 -0800, david.lloyd at
>>>   ...  I've added the following methods to Layer.Controller:
>>> public Controller addPackage(Module source, String pn) { ... }
>>> public Controller addOpens(Module source, String pn, Module target) { ... }
>>> public Controller addOpensToAll(Module source, String pn) { ... }
>>> public Controller addOpensToAllUnnamed(Module source, String pn) { ... }
>>> public Controller addExports(Module source, String pn, Module target) {
>>> ... }
>>> public Controller addExportsToAll(Module source, String pn) { ... }
>>> public Controller addExportsToAllUnnamed(Module source, String pn) { ... }
>>> public Controller addUses(Module source, Class<?> service) { ... }
>> Can you explain exactly why you need all these methods?
>> I can see why you might need the qualified `addExports` method, akin
>> to the existing `addOpens` method, if you're doing some form of module
>> resolution on your own that's somehow taking named layers, or whatever,
>> into account.
> Yeah we're assembling the module structure in a multi-stage lazy 
> resolution process, thus we don't know exactly what we're opening or 
> exporting until after all contents and dependencies are defined (and 
> this can change over time).

Hmm.  This seems to be a fundamental difference between JBoss modules and
OSGi.  Once an OSGi bundle is loaded then its exports don't change, at
least not until it's updated, and this is part of what enables Watson's
JPMS embedding to work.

>> The `add{Opens,Exports}ToAll` variants shouldn't be needed since you can
>> just include unqualified `open` and `exports` directives in the module
>> descriptor that you're going to build anyway.  That has the additional
>> benefit of making the exports apparent to the JPMS resolver so that JPMS
>> modules can resolve against your modules, whereas invoking these methods
>> wouldn't do that.
> The problem is that when I first build the module, I don't have all the 
> dependency information available, and also some of the dependencies will 
> include modules which are not visible to the layer (in fact right now 
> I'm putting each module into a separate layer), and some of the 
> dependencies are on non-Jigsaw entities which I also can't know initially.
>> The `addPackage` method is problematic, in part since it's quite slow
>> (at least in HotSpot, where we've optimized for the common case of the
>> set of packages in a module never changing).  Can't you compute the set
>> of packages in a module at the time you create the descriptor?
> Two things prevent this: firstly, we don't have the module contents 
> until after we've constructed the module class loader, which requires 
> the layer controller in order to process dependencies, so as of now, 
> adding contents depends on having the module established.  Secondly, it 
> is allowed to add content to a JBoss module after it has been 
> established.  The first might be fixable, but I can't think of a way 
> around the second.

Me neither.

For any kind of Watson-style embedding of JBoss modules in JPMS to work
then there has to be a point in time at which you can say "okay, this
JBoss module is in a stable state, let's spin up a JPMS module descriptor
for it so that the JPMS resolver can resolve some JPMS modules against
it."  If the JBoss module is updated later on then you create a new JPMS
module descriptor for it and re-resolve any JPMS modules that used to
depend upon it.

Can you, in general, identify such points in time for JBoss modules?

If so, then I don't think you need the above methods.  The JPMS module
descriptor that you construct needn't capture all the details of the
corresponding JBoss module.  In fact it can't, since JBoss modules can
relate to each other in ways that aren't expressible in JPMS.  That's
fine, though -- the module descriptor need only expose the information
that the JPMS resolver needs for actual JPMS modules, mainly `opens`,
`exports`, and `requires transitive`.

If not, then adding the above methods won't help you anyway.  They only
affect the run-time state of modules, i.e., the state known to the JVM
and surfaced in `java.lang.reflect.Module`.  The JPMS resolver doesn't
read the run-time state but, rather, the configurations computed by
earlier invocations of the resolver, and ultimately those are all based
on module descriptors, over in the `java.lang.module` package.

- Mark

More information about the jpms-spec-observers mailing list