A compromise approach on module isolation

David M. Lloyd david.lloyd at redhat.com
Thu May 11 23:17:45 UTC 2017


In the wake of the PR vote, one of the most oft-cited unmet expectations 
was the lack of package namespace isolation among modules.  I'd like to 
propose a patch [1] which would allow this type of module isolation to 
be used by the run time on an opt-in or opt-out basis.

Justification:

• Large applications are more likely to encounter concealed and 
non-concealed package conflicts.
• By making the change opt-in or opt-out, any application which expects 
all of its modules to be loaded by a single class loader can still 
function, while allowing more complex applications (which already would 
necessarily have required at least some separated class loaders) to 
continue to work.
• The patch seems to have a small complexity and maintenance footprint.

Drawbacks:

None that I am aware of.

Patch information:

The approach of this patch simply looks for a system property and, 
depending on the value of this property, establishes isolated module 
loaders.  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.

Other than the system property (which is just one possible approach), no 
API or specification changes should be needed.  This version uses the 
property "jdk.module.isolated" defaulting to "false".

[1]:

diff --git 
a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java 
b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
index d976aab..f06adfb 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
@@ -112,6 +112,15 @@ public static ClassLoader appClassLoader() {
      }

      /**
+     * Returns a new isolated application module class loader.
+     *
+     * @return the new application module class loader (not {@code null})
+     */
+    public static ClassLoader appModuleClassLoader() {
+        return new AppModuleClassLoader(APP_LOADER);
+    }
+
+    /**
       * The class loader that is used to find resources in modules 
defined to
       * the boot class loader. It is not used for class loading.
       */
@@ -220,6 +229,21 @@ protected Package defineOrCheckPackage(String pn, 
Manifest man, URL url) {
      }

      /**
+     * An isolated application module class loader that is a {@code 
BuiltinClassLoader} with
+     * the application class loader as parent.
+     */
+    private static class AppModuleClassLoader extends BuiltinClassLoader {
+        static {
+            if (!ClassLoader.registerAsParallelCapable())
+                throw new InternalError();
+        }
+
+        AppModuleClassLoader(AppClassLoader parent) {
+            super("app", parent, null);
+        }
+    }
+
+    /**
       * Returns a {@code URLClassPath} of file URLs to each of the 
elements in
       * the given class path.
       */
diff --git 
a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java 
b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java
index b0f465d..cc2bdb6 100644
--- 
a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java
+++ 
b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleLoaderMap.java
@@ -85,6 +85,8 @@ public ClassLoader apply(String name) {
          return platformModules;
      }

+    private static final boolean ISOLATED_MODULE_PATH = 
Boolean.parseBoolean(System.getProperty("jdk.module.isolated", "false"));
+
      /**
       * Returns the function to map modules in the given configuration 
to the
       * built-in class loaders.
@@ -102,6 +104,8 @@ public ClassLoader apply(String name) {
              if (!bootModules.contains(mn)) {
                  if (platformModules.contains(mn)) {
                      map.put(mn, platformClassLoader);
+                } else if (ISOLATED_MODULE_PATH) {
+                    map.put(mn, ClassLoaders.appModuleClassLoader());
                  } else {
                      map.put(mn, appClassLoader);
                  }


-- 
- DML


More information about the jpms-spec-observers mailing list