David M. Lloyd
david.lloyd at redhat.com
Mon Jan 30 15:13:10 UTC 2017
On 01/27/2017 04:24 PM, mark.reinhold at oracle.com wrote:
> 2017/1/27 9:53:23 -0800, forax at univ-mlv.fr:
>> 2017/1/26 14:36:31 -0800, mark.reinhold at oracle.com:
>>> 2016/12/15 9:20:51 -0800, forax at univ-mlv.fr:
>>>> 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
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