< prev index next >

src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java

Print this page

@@ -40,22 +40,23 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
-import jdk.internal.loader.BootLoader;
-import jdk.internal.loader.BuiltinClassLoader;
 import jdk.internal.access.JavaLangAccess;
 import jdk.internal.access.JavaLangModuleAccess;
 import jdk.internal.access.SharedSecrets;
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.BuiltinClassLoader;
+import jdk.internal.loader.ClassLoaders;
+import jdk.internal.misc.VM;
 import jdk.internal.perf.PerfCounter;
 
 /**
  * Initializes/boots the module system.
  *

@@ -84,12 +85,12 @@
 
     // the token for "all modules on the module path"
     private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
 
     // access to java.lang/module
-    private static final JavaLangModuleAccess JLMA
-        = SharedSecrets.getJavaLangModuleAccess();
+    private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
+    private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
 
     // The ModulePatcher for the initial configuration
     private static final ModulePatcher patcher = initModulePatcher();
 
     /**

@@ -132,18 +133,62 @@
             return finder;
         }
     }
 
     /**
-     * Initialize the module system, returning the boot layer.
+     * Returns true if the archived boot layer can be used. The system properties
+     * are checked in the order that they are used by boot2.
+     */
+    private static boolean canUseArchivedBootLayer() {
+        return getProperty("jdk.module.upgrade.path") == null &&
+               getProperty("jdk.module.path") == null &&
+               getProperty("jdk.module.patch.0") == null &&    // --patch-module
+               getProperty("jdk.module.main") == null &&
+               getProperty("jdk.module.addmods.0") == null  && // --add-modules
+               getProperty("jdk.module.limitmods") == null &&
+               getProperty("jdk.module.addreads.0") == null &&    // --add-reads
+               getProperty("jdk.module.addexports.0") == null &&  // --add-exports
+               getProperty("jdk.module.addopens.0") == null &&    // --add-opens
+               getProperty("jdk.module.illegalAccess") == null;
+    }
+
+    /**
+     * Initialize the module system, returning the boot layer. The boot layer
+     * is obtained from the CDS archive if possible, otherwise it is generated
+     * from the module graph.
      *
      * @see java.lang.System#initPhase2(boolean, boolean)
      */
-    public static ModuleLayer boot() throws Exception {
-
+    public static ModuleLayer boot() {
         Counters.start();
 
+        ModuleLayer bootLayer;
+        ArchivedBootLayer archivedBootLayer = ArchivedBootLayer.get();
+        if (archivedBootLayer != null) {
+            assert canUseArchivedBootLayer();
+            bootLayer = archivedBootLayer.bootLayer();
+            BootLoader.getUnnamedModule(); // trigger <clinit> of BootLoader.
+            VM.defineArchivedModules(ClassLoaders.platformClassLoader(), ClassLoaders.appClassLoader());
+
+            // assume boot layer has at least one module providing a service
+            // that is mapped to the application class loader.
+            JLA.bindToLoader(bootLayer, ClassLoaders.appClassLoader());
+
+            // IllegalAccessLogger needs to be set
+            var illegalAccessLoggerBuilder = archivedBootLayer.illegalAccessLoggerBuilder();
+            if (illegalAccessLoggerBuilder != null) {
+                illegalAccessLoggerBuilder.complete();
+            }
+        } else {
+            bootLayer = boot2();
+        }
+
+        Counters.publish("jdk.module.boot.totalTime");
+        return bootLayer;
+    }
+
+    private static ModuleLayer boot2() {
         // Step 0: Command line options
 
         ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
         ModuleFinder appModulePath = finderFor("jdk.module.path");
         boolean isPatched = patcher.hasPatches();

@@ -426,10 +471,11 @@
             exportedPackagesToOpen = archivedModuleGraph.exportedPackagesToOpen();
         } else {
             concealedPackagesToOpen = systemModules.concealedPackagesToOpen();
             exportedPackagesToOpen = systemModules.exportedPackagesToOpen();
         }
+        IllegalAccessLogger.Builder builder =
         addIllegalAccess(upgradeModulePath,
                          concealedPackagesToOpen,
                          exportedPackagesToOpen,
                          bootLayer,
                          extraExportsOrOpens);

@@ -440,25 +486,25 @@
             unlimitedFinder = new SafeModuleFinder(savedModuleFinder);
             if (savedModuleFinder != finder)
                 limitedFinder = new SafeModuleFinder(finder);
         }
 
-        // Module graph can be archived at CDS dump time. Only allow the
-        // unnamed module case for now.
+        // Archive module graph and boot layer can be archived at CDS dump time.
+        // Only allow the unnamed module case for now.
         if (canArchive && (mainModule == null)) {
-            ArchivedModuleGraph.archive(
-                    new ArchivedModuleGraph(hasSplitPackages,
+            ArchivedModuleGraph.archive(hasSplitPackages,
                                             hasIncubatorModules,
                                             systemModuleFinder,
                                             cf,
                                             clf,
                                             concealedPackagesToOpen,
-                                            exportedPackagesToOpen));
-        }
+                                        exportedPackagesToOpen);
 
-        // total time to initialize
-        Counters.publish("jdk.module.boot.totalTime");
+            if (!hasSplitPackages && !hasIncubatorModules) {
+                ArchivedBootLayer.archive(bootLayer, builder);
+            }
+        }
 
         return bootLayer;
     }
 
     /**

@@ -749,21 +795,22 @@
 
     /**
      * Process the --illegal-access option (and its default) to open packages
      * of system modules in the boot layer to code in unnamed modules.
      */
-    private static void addIllegalAccess(ModuleFinder upgradeModulePath,
+    private static IllegalAccessLogger.Builder
+        addIllegalAccess(ModuleFinder upgradeModulePath,
                                          Map<String, Set<String>> concealedPackagesToOpen,
                                          Map<String, Set<String>> exportedPackagesToOpen,
                                          ModuleLayer bootLayer,
                                          boolean extraExportsOrOpens) {
         String value = getAndRemoveProperty("jdk.module.illegalAccess");
         IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT;
         if (value != null) {
             switch (value) {
                 case "deny":
-                    return;
+                    return null;
                 case "permit":
                     break;
                 case "warn":
                     mode = IllegalAccessLogger.Mode.WARN;
                     break;

@@ -771,11 +818,11 @@
                     mode = IllegalAccessLogger.Mode.DEBUG;
                     break;
                 default:
                     fail("Value specified to --illegal-access not recognized:"
                             + " '" + value + "'");
-                    return;
+                    return null;
             }
         }
         IllegalAccessLogger.Builder builder
             = new IllegalAccessLogger.Builder(mode, System.err);
 

@@ -834,15 +881,15 @@
 
             // log reflective access to non-public members/types in exported packages
             builder.logAccessToExportedPackages(m, exportedPackages);
 
             // open the packages to unnamed modules
-            JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
-            jla.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
+            JLA.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
         }
 
         builder.complete();
+        return builder;
     }
 
     /**
      * Decodes the values of --add-reads, -add-exports, --add-opens or
      * --patch-modules options that are encoded in system properties.

@@ -903,15 +950,23 @@
      */
     private static Map<String, List<String>> decode(String prefix) {
         return decode(prefix, ",", true);
     }
 
+
+    /**
+     * Gets the named system property
+     */
+    private static String getProperty(String key) {
+        return System.getProperty(key);
+    }
+
     /**
      * Gets and remove the named system property
      */
     private static String getAndRemoveProperty(String key) {
-        return (String)System.getProperties().remove(key);
+        return (String) System.getProperties().remove(key);
     }
 
     /**
      * Checks incubating status of modules in the configuration
      */
< prev index next >