Configurations... (Was: Re: Module-system requirements)
David M. Lloyd
david.lloyd at redhat.com
Tue Mar 17 13:02:21 UTC 2015
On 03/16/2015 03:44 PM, mark.reinhold at oracle.com wrote:
> 2015/3/11 6:38 -0700, david.lloyd at redhat.com:
>> ...
>>
>> Maybe what we need is a clearer definition of "Configuration" as it is
>> only defined as a side-effect of Resolution: "The resulting
>> configuration contains all of the code and data required to compile or
>> run the initial module." And Linking is AFAICT the first section that
>> implies that Configurations actually contain modules in any way. This
>> might help me understand what a tree topology actually means.
>
> A configuration is the result of resolution and service binding. You
> can think of it as a graph, with modules for nodes, edges for module
> dependences, and edges (of a different color) for service-provider
> bindings.
>
> I'm pretty sure that a configuration, in this sense, is not analogous
> to what you call a module loader in your system. A configuration can
> be loaded by a single class loader, multiple class loaders, or even one
> class loader per module, but the module system shouldn't mandate any
> particular approach.
In our case the module loader is the instigator (not the result) of
resolution. Resolution happens lazily, very much like class loading.
The result of resolution is thus completely abstract and not represented
programmatically. This also means that there is no single resolve step
at run time; instead each module is efficiently linked as it is loaded
using a relatively simple traversal algorithm, regardless of what module
loader contains the dependency being linked in, which allows the system
to support an unbounded number of modules. Any expensive or complex
resolution processes are part of build or distribution.
> If you build a dynamic configuration on top of the initial configuration,
> and then another on top of that, as you might do in something like an
> application server, then the union of their graphs will be a DAG (at
> least) but the configurations themselves are just in a list, somewhat
> like a search path. You can imagine having multiple such lists sharing
> prefixes, i.e., a tree of configurations, but to resolve a dependence in
> any particular configuration you only need to consult its parent
> configurations.
OK, but if (say) a dynamic configuration can override service-provider
bindings, then how does a parent configuration know to use the
overridden bindings for services it provides? I can't imagine any
scheme at all which would necessitate that the entire configuration be a
list. Maybe conflating module dependencies and service provider
configuration into one "thing" is an error?
> If configurations can be related in a more general way, i.e., in a DAG,
> then the resolution algorithm becomes more complex. Do we actually need
> that? I've yet to see any use cases.
I don't know about framing in terms of configurations, because we don't
do that. But I think that modules from one system should be able to
express dependencies on other modules from any other system regardless
of their relationship, at least on a programmatic basis. This is
necessary if you want two completely different module systems to
interact, because you cannot always assume that (for example) one
namespace can just be polluted with names from another (parent)
namespace, nor can you assume that a given configuration would only ever
want to interact (link) with one other configuration (this is akin to
the logic of moving away from a strict class loader hierarchy). We made
this mistake early on, and fixing it resulted in a much better system,
which allowed us to have a more logical arrangement between OSGi, EE,
the JDK, distribution modules, extension modules, and filesystem JAR
modules without worrying about what ended up being a pretty arbitrary
constraint. Each module loader interacted with the others in specific
and completely separate ways (which also greatly helps in terms of
letting the container bind module dependencies with service
dependencies, to ensure that things are actually started in the right
order). For example if I want to link in a filesystem JAR, I use
Class-Path (in the MANIFEST). However, the Extension-List mechanism is
totally different (and has a different namespace), our distribution
module Dependencies mechanism is different again, and OSGi is
*completely* different in every possible way. So, there was really no
reason to force all of these resolution strategies to go down the same pipe.
It's not really clear to me in any event what makes the resolution
algorithm more complex in graph vs. list form; as of yet we don't really
have a description of what the algorithm you have in mind actually does,
and how and why it does it. So there's probably a more in-depth
discussion to be had. But if there's a way for any configuration to
contain module dependencies on any other configuration, then maybe the
constraint is only practically limited to service resolution and I'm
worried about nothing.
--
- DML
More information about the jpms-spec-observers
mailing list