#LayerPrimitives should be re-opened
David M. Lloyd
david.lloyd at redhat.com
Fri Feb 24 15:16:07 UTC 2017
I am requesting that the #LayerPrimitives issue be re-opened.
This issue requested the ability for Layer.Controller to perform the
following operations, which Modules can already do for themselves (and,
by extension, Layers can do as well using bytecode injection):
• addExports(Module source, String packageName, Module target) -
equivalent to Module#addExports(String packageName, Module target),
"source" must be in the controller's corresponding layer
• addUses(Module source, Class<?> service) - equivalent to
Module#addUses(Class<?> service), "source" must be in the controller's
corresponding layer
These two methods should be added because requiring bytecode injection
to perform these functions is unreasonably onerous, which alone should
be enough to justify re-opening the issue.
The following self-explanatory operations do not have corresponding
methods on Module, and normally can only be done by editing the
descriptor or using the Instrumentation#redefineModule(...) API to do so:
• addOpensToAll(Module source, String packageName)
• addExportsToAll(Module source, String packageName)
It is not always possible for a container to know what packages need to
be exported or opened to all when the module is built, especially in a
dynamic deployment environment like ours. Note that
Controller#addOpens(Module source, String packageName, Module target) is
already an existent method on Controller thus is already deemed "safe".
The following operations neither have corresponding methods on Module,
nor can be done by editing the descriptor AFAIK:
• addOpensToAllUnnamed(Module source, String packageName)
• addExportsToAllUnnamed(Module source, String packageName)
The latter is arguably not necessary since unnamed modules are usually
not going to be bound by JPMS linkage, so from what I understand, the
exports usually won't apply in this case anyway. It seems to me that
the former method might be of use in some cases; having unnamed module
code reflecting on module code does not seem very outlandish to me,
especially in a container environment.
This leaves addPackage(Module source, String packageName). This method
is not available on Module and can only otherwise be done by editing the
descriptor or using Instrumentation#redefineModule(...). However, if
your loader does not yet know the complete set of packages (i.e. it's
lazy), or the set of packages might be supplemented after the module is
initially created, you either need this method, or you have to redesign
your container's linkage strategy from the ground up. We definitely
need this method. One OSGi implementer has indicated that they can live
without it (by not implementing some optional pieces, and mandating
strict behavior where other containers had flexibility previously) but
I've also reached out to a few others to see if I can get more data
about this. I know that JBoss OSGi does presently rely on this sort of
functionality already; I am not sure if it is limited to fragment
support or if there is more to it. I have a query out to the maintainer
of that project (Arcadiy Ivanov) to get further information, but I
understand he is traveling at the moment.
However, the potential of the OSGi requirement is not a necessary
condition for this method to be justified. We believe that it is also
very useful when delivering a Java EE container; we have relied on this
functionality for many years. There are not many Java EE certified
vendors in the world, so I would consider this alone to be just as
substantial a justification for the feature. Logically it is possible
to deliver a Java EE container without it, just as it is possible to
deliver an OSGi container without it, but this means the end of certain
features which a massive number of users have relied upon.
This excludes other possible uses, like: dynamic code discovery (via
network for example), IDE code hot-deployment features which would
require Instrumentation otherwise, etc.
The patch itself (still viewable here [1]) is very small, mostly
consisting of JavaDoc, and only utilizes existing functions in Jigsaw.
It does not introduce any new implementation behavior, and is only
available to Layer implementers, therefore I would consider the risk to
be very small by any concrete or objective measure.
These primitives also have the advantage of enabling an acceptable
solution to the following issues (at minimum):
• #NonHierarchicalLayers
• #CyclicDependences (at least, within containers)
• #MutableConfigurations
And can be used to provide container-based solutions to several others
as well. To me this looks like a very big reward for low risk.
My patch also proposed a trivial one-line fix to remove a double null
check from the existing Controller#addOpens(Module, String, Module)
method. This may have been fixed upstream already, but because a storm
has disabled my network connection, I cannot verify this easily at present.
If the problem with the issue is the total set of methods, I'm OK with
dividing the issue up and arguing the merits of each.
I think this issue should be re-opened, and I think that doing so, with
a view towards satisfactory resolution, is in the best interests of the
community as well as the majority of the members of this expert group.
[1] https://gist.github.com/dmlloyd/e3c114f0ac7595a93ecb63b1dbed5e00
--
- DML
More information about the jpms-spec-experts
mailing list