Layer Primitives (3/3): addPackage()
David M. Lloyd
david.lloyd at redhat.com
Wed May 10 22:08:04 UTC 2017
Saving the controversial one for last: I'd like to re-propose adding the
following method to the layer controller specification and
implementation [1].
Justification:
• Existing containers and frameworks from multiple vendors and
developers have the ability to add static and dynamic content to
applications at run time for a variety of reasons and with a variety of
security requirements.
• A very large number of Java users are using Java by way of such
containers and frameworks; this functionality is generally useful.
• Containers and frameworks _will_ be using JPMS modules dynamically in
order (at minimum) to take advantage of the security benefits provided
thereby; the ModuleLayer.Controller API exists in recognition of this fact.
• While it is possible, via various techniques, to provide the illusion
of adding modular content at run time by other means, these other
techniques introduce various user-visible problems that can lead to
undue confusion and difficulty; additionally, it would result in a
fairly substantial increase in downstream complexity for containers,
whereas the upstream complexity should be considerably less and can be
utilized by all.
• The controller is only available to user-defined Layers, so there is
no risk or exposure to the platform, jlink, etc.
• The proposed behavior is very consistent with the existing behavior of
the module system and its implementation, and as such can be implemented
in terms of functionality already necessarily existent in the current
JDK codebase.
• The patch itself is very small.
Drawbacks:
• The platform would have to be specified to have the capability to
dynamically register a package-to-module mapping for any user-managed
Layer, which would be used for subsequent diagnostic and security
calculations. This is significantly mitigated by the fact that the
reference implementation already has the required capability. It is
also mitigated by the fact that the implementation would not need to
provide or support this ability for JDK-managed layer(s).
• A determination would have to be made as to whether the supplemental
package would figure into resolver calculations; however, this should be
mitigated by the fact that it is already possible to dynamically add
exports. Exporting a freshly minted package should be no different from
exporting a previously hidden but existent package as far as it is
concerned; the implementation seems to square with this idea. This can
be discussed further if some new information comes to light.
• Adding code dynamically may theoretically introduce various
deoptimizations in the compiler (JIT) implementation. However, adding a
package alone should not introduce any such cases that do not already
exist by adding classes or packages to the unnamed module, or by
defining classes into existent packages within a module. It is
understood to be unlikely that the compiler would have to make any
special consideration for this case. This can be discussed further if
some new information comes to light.
• The complexity and maintenance cost seems be quite low, but is not
zero. However, the gain to container developers, and indirectly the
value to users thereby, should outweigh the complexity and maintenance
cost; dynamic and self-modifying code has been a foundation capability
of Java since the 1990s. Enabling dynamic containers in what could be a
substantial way, especially at such a low cost, should be considered a
worthwhile goal that will benefit a large portion of the community.
This can be discussed further if it is shown that the complexity or
maintenance cost is likely to be more substantial than expected or if
new information comes to light.
Patch information:
The content and format of the JavaDoc are drawn from neighboring
methods. I relinquish any copyright claim to the patch in this mail.
Please do not get bogged down by any formatting problems introduced by
the mailing list; the purpose of directly including the patch is to give
a clear, unambiguous subject for discussion. I can provide a proper
webrev (or whatever other form is requested) if needed. This patch
applies atop the previous (2/3) patch, but can trivially be applied
without it as well.
[1]:
diff --git a/jdk/src/java.base/share/classes/java/lang/Module.java
b/jdk/src/java.base/share/classes/java/lang/Module.java
index f6ab49b..789d02f 100644
--- a/jdk/src/java.base/share/classes/java/lang/Module.java
+++ b/jdk/src/java.base/share/classes/java/lang/Module.java
@@ -1016,7 +1016,7 @@ public final class Module implements
AnnotatedElement {
* @throws IllegalArgumentException if the package name is not legal
* @throws IllegalStateException if the package is defined to
another module
*/
- private void implAddPackage(String pn, boolean syncVM) {
+ void implAddPackage(String pn, boolean syncVM) {
// no-op if unnamed module
if (!isNamed())
return;
diff --git a/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java
b/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java
index 541be5f..7cb6377 100644
--- a/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java
+++ b/jdk/src/java.base/share/classes/java/lang/ModuleLayer.java
@@ -332,6 +332,31 @@ public final class ModuleLayer {
return this;
}
+
+ /**
+ * Updates module {@code source} in the layer to contain a new
package.
+ * This method is a no-op if {@code source} already contains
package {@code pn}.
+ *
+ * @param source
+ * The source module
+ * @param pn
+ * The package name to add
+ *
+ * @return This controller
+ *
+ * @throws IllegalArgumentException
+ * If {@code pn} is {@code null}, or {@code source} is
not in the layer
+ */
+ public Controller addPackage(Module source, String pn) {
+ Objects.requireNonNull(source);
+ if (pn == null)
+ throw new IllegalArgumentException("package is null");
+ if (source.isNamed()) {
+ ensureInLayer(source);
+ source.implAddPackage(pn, true);
+ }
+ return this;
+ }
}
--
- DML
More information about the jpms-spec-experts
mailing list