Proposal: #VersionedDependences

David M. Lloyd david.lloyd at
Mon Jan 30 15:13:10 UTC 2017

On 01/27/2017 04:24 PM, mark.reinhold at wrote:
> 2017/1/27 9:53:23 -0800, forax at
>> 2017/1/26 14:36:31 -0800, mark.reinhold at
>>> 2016/12/15 9:20:51 -0800, forax at
>>>> ...
>>>> The issue asks to be able to store a version strings or a constraints.
>>>> It can be interpreted as two different things.
>>>> - the configuration used by example by Maven which uses constraints
>>>> that will be resolved,
>>>> - the other is the effectively resolved versions which is what this
>>>> proposal do.
>>>> In my opinion, storing the former info maybe more interesting for a
>>>> language (the actual configuration) than storing the later.
>>> Storing version constraints might be more interesting, but we can't
>>> do that in JPMS since JPMS (intentionally) does not have a concept of
>>> version constraints.
>> yes, but given that a version is a string, you should be able to store
>> anything in it, if the value is not inserted by javac but by jar.
> A version is not just a string, and we should not encourage people to
> use versions to encode information that's not a version.

This is a fair point, however, see below.

>>> ...
>>> These strings are no less standard than any of the other information
>>> exposed in the standard `ModuleDescriptor` API, so recording them in
>>> the main `Module` attribute seems perfectly appropriate.
>> It's something we have swept under the rug, but the version (of the
>> module or of requires) format should not be Java specific.
> It should be as general as possible but it should be well-specified.
> In that sense it will be Java-specific.
>> I see no problem to have the ModuleBuilder to enforce a specific
>> format but a ModuleDescriptor should return an Optional<String> (it
>> can also retruns an Optional<Version> in an overloaded method but it
>> should be possible to get the string version).
>> Version format depends on the module system, it should be enforced by
>> the code that creates the Layer.
> Yes, the version format depends on the module system, and that module
> system is JPMS.  We're not designing multiple different module systems,
> nor a low-level framework upon which multiple different module systems
> can be implemented.

But unfortunately we are, and we must.  You cannot hide behind "we're 
only implementing one module system" while at the same time creating the 
JVM diagnostic and security features which *should* be applicable to any 
module system but *can* only be exploited by the one.  And it is 
certainly irresponsible to implement a top-to-bottom module system like 
this, in such a way as to ensure that it exclusively has the ability to 
exploit such features, on the assumption that somehow it is either 
sufficient or can be made sufficient for all use cases, while at the 
same time either disregarding or narrowly cherry-picking requirements 
and experience from existing frameworks, particularly when several such 
frameworks exist and are used in the wild.

Indeed in hindsight it appears that it would have been far more logical 
to have *started* with a low-level framework to support additional 
diagnostics and security for user class loader implementations, 
modularizing just the JDK at first, and to have built it up over 
subsequent JDK releases to include a Java user API for modules, a 
deployment format, and compiler support once the bugs were worked out 
(and it would certainly have been far less likely to have delayed Java 9 
this long in such a case).

But we are where we are, and the only reasonable compromise at this 
point is to provide the new deployment format while at the same time 
creating hooks to support others, including those for which naming or 
versioning schemes differ (perhaps dramatically) from the proposed 
deployment format.

 From the perspective of the characteristics of the modular deployment 
format: if Red Hat signs off on this specification, it is not going to 
be because the deployment format is good, or correct, or covers all use 
cases, but rather because there are ways to mitigate the problems in the 
case that it is not.

>  The JPMS version format attempts to encompass a
> wide variety of existing version schemes, but it does not (and can not)
> encompass them all.

Absolutely.  But it's the Layer provider which *can* do so, and should 
be able to do so.  This can easily be mitigated by putting version 
validation (and collation, if such a thing is to be allowed) policy on 
the Layer implementation.  Users will not manually encode garbage into 
the version string if the resultant module is not loadable; in this way, 
such a Layer-oriented policy is identical to the current policy.

Speaking in terms of implementation - the current List<Whatever> 
implementation is not very good for a bunch of reasons.  A simple String 
(guarded by the Layer's validation policy of course) would work far more 
efficiently, and if collation is to be supported, a Comparator 
implementation matching the validation rules that simply operates on the 
code points of the string is not only possible but reasonably easy to 
do.  I implemented just such a simple DFA-style parser for jboss-modules 
which works for a combination parser and comparator and the whole thing 
clocks in at just around 100 lines for the parser methods plus a few 
small support methods.  The whole thing, from comments to copyright to 
serialization to an additional API that allows iterating the version 
segments, is under 600 LOC.  The memory savings of such an approach 
should be fairly substantial, not to mention eliminating some generics 
and other weirdness.


More information about the jpms-spec-observers mailing list