Proposal: #NonHierarchicalLayers

David M. Lloyd david.lloyd at
Wed Feb 15 22:32:06 UTC 2017

On 02/15/2017 01:51 PM, mark.reinhold at wrote:
> 2017/1/30 7:13:31 -0800, david.lloyd at
>> On 01/26/2017 04:34 PM, mark.reinhold at wrote:
>>> 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.
>> OSGi does support dynamic attachments of fragments.  The current
>> prototype cannot do this but on Jan. 4 Thomas expressed that being able
>> to add packages would enable this part of the specification.  Re-linking
>> everything is (according to this email) an alternative that comes at the
>> cost of not supporting this feature.
> True, but Thomas later recommended against complicating JPMS in order to
> support this feature of OSGi [1].  He can live with having to re-resolve
> bundles when fragments add API packages, which is not common and arguably
> an anti-pattern.

Sure, it's possible that OSGi implementations can get away with it, as 
few users seem to care much about such strict spec adherence and perhaps 
the spec will be modified to take the new restrictions into account.

>>> 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.
>> In order to do this we have to shut down all existing deployments in the
>> container that have any kind of dependency relationship, and restart
>> them.  This is not really acceptable as it defeats the purpose of the
>> mechanism.
>>> Can you, in general, identify such points in time for JBoss modules?
>> Any time the user deploys additional or replacement content is a point
>> where a module may need to be updated.
>>> 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.
>> Currently the prototype code does not use the JPMS resolver.  From my
>> understanding, the JVM tables mediate access control, but the actual
>> linkage between classes at run time happens via
>> java.lang.ClassLoader#findClass(java.lang.String, java.lang.String).  As
>> long as this method resolves
> This sentence is incomplete, so I'm not sure what you meant to say here.

Something like "as long as this method resolves classes in modules then 
we'll be fine".

> At any rate, if you're not eventually going to use the JPMS resolver to
> resolve some JPMS modules against some JBoss modules, in order to obtain
> bidirectional interoperation as is now possible with OSGi [2], then why
> bother with any of this?

I don't want to.  Even with all of our outstanding issues resolved, this 
end product is not what we'd hoped for and is at best a partial 
compromise, and in my mind represents far too radical a change in far 
too short of a time frame.  In many ways it runs flatly counter to what 
we've learned and accomplished these past several years in our own 

The reality though is that if the platform includes a new deployment 
format with new behaviors, some users will soon expect that this format 
and its corresponding behaviors to be supported by containers, because 
it will be viewed by many to be a standard.

It's possible that we can support this expectation to an extent simply 
by adding a separated JPMS container, and that would be a good option 
for that purpose.  However that leaves our existing deployment model 
forever deficient because of its relative lack of encapsulation 
features, and to a lesser extent, reliance on "fake" module diagnostics, 
to speak nothing of compatibility oddities for users going from one to 
the other.  If we want to bring our existing deployment model with all 
its features up to date with the new encapsulation capabilities, we 
either need to find a way to utilize Jigsaw to do it (which is what I'm 
trying to accomplish here), or else we need some new API which allows us 
to establish similar behaviors at a class loader level.

Otherwise, you're right: if we can't take advantage of the useful 
capabilities of JPMS on our own terms, then why would we vote to support 
what amounts to a competing module architecture and deployment format, 
which actively undermines alternative systems which can't or won't abide 
by its restrictions (by the combination of establishing that the JPMS is 
not a meta-module system, yet also restricting key JVM features to only 
that system, and ensuring that differing behavioral characteristics 
(like version numbers or descriptor formats for example) either conform 
or are relegated to second-class behaviors), and which from our point of 
view has several critical deficiencies and substantial compatibility 
problems compared to what we have today?

The only reason we would do, for the lack (via the above reasons) of 
inherently representing a good forward evolution for us, is if it 
provided a way for us to coexist while also giving us similar 
capabilities.  Otherwise we frankly shouldn't support such a system at 
all, and I would hope to persuade others of the same.


More information about the jpms-spec-experts mailing list