< prev index next >

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

Print this page
rev 57859 : 8237484: Improve module system bootstrap
Reviewed-by: alanb
   1 /*
   2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 123      * Returns the ModuleFinder for the initial configuration.
 124      *
 125      * @apiNote Used to support "{@code java --list-modules}".
 126      */
 127     public static ModuleFinder limitedFinder() {
 128         ModuleFinder finder = limitedFinder;
 129         if (finder == null) {
 130             return unlimitedFinder();
 131         } else {
 132             return finder;
 133         }
 134     }
 135 
 136     /**
 137      * Initialize the module system, returning the boot layer.
 138      *
 139      * @see java.lang.System#initPhase2(boolean, boolean)
 140      */
 141     public static ModuleLayer boot() throws Exception {
 142 
 143         // Step 0: Command line options
 144 
 145         long t0 = System.nanoTime();
 146 
 147         ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
 148         ModuleFinder appModulePath = finderFor("jdk.module.path");
 149         boolean isPatched = patcher.hasPatches();
 150 
 151         String mainModule = System.getProperty("jdk.module.main");
 152         Set<String> addModules = addModules();
 153         Set<String> limitModules = limitModules();
 154 
 155         PrintStream traceOutput = null;
 156         String trace = getAndRemoveProperty("jdk.module.showModuleResolution");
 157         if (trace != null && Boolean.parseBoolean(trace))
 158             traceOutput = System.out;
 159 

 160 
 161         // Step 1: The observable system modules, either all system modules
 162         // or the system modules pre-generated for the initial module (the
 163         // initial module may be the unnamed module). If the system modules
 164         // are pre-generated for the initial module then resolution can be
 165         // skipped.
 166 
 167         long t1 = System.nanoTime();
 168 
 169         SystemModules systemModules = null;
 170         ModuleFinder systemModuleFinder;
 171 
 172         boolean haveModulePath = (appModulePath != null || upgradeModulePath != null);
 173         boolean needResolution = true;
 174         boolean canArchive = false;
 175         boolean hasSplitPackages;
 176         boolean hasIncubatorModules;
 177 
 178         // If the java heap was archived at CDS dump time and the environment
 179         // at dump time matches the current environment then use the archived
 180         // system modules and finder.
 181         ArchivedModuleGraph archivedModuleGraph = ArchivedModuleGraph.get(mainModule);
 182         if (archivedModuleGraph != null
 183                 && !haveModulePath
 184                 && addModules.isEmpty()
 185                 && limitModules.isEmpty()
 186                 && !isPatched) {
 187             systemModuleFinder = archivedModuleGraph.finder();
 188             hasSplitPackages = archivedModuleGraph.hasSplitPackages();


 198             }
 199             if (systemModules == null) {
 200                 // all system modules are observable
 201                 systemModules = SystemModuleFinders.allSystemModules();
 202             }
 203             if (systemModules != null) {
 204                 // images build
 205                 systemModuleFinder = SystemModuleFinders.of(systemModules);
 206             } else {
 207                 // exploded build or testing
 208                 systemModules = new ExplodedSystemModules();
 209                 systemModuleFinder = SystemModuleFinders.ofSystem();
 210             }
 211 
 212             hasSplitPackages = systemModules.hasSplitPackages();
 213             hasIncubatorModules = systemModules.hasIncubatorModules();
 214             // not using the archived module graph - avoid accidental use
 215             archivedModuleGraph = null;
 216         }
 217 
 218         Counters.add("jdk.module.boot.1.systemModulesTime", t1);
 219 
 220 
 221         // Step 2: Define and load java.base. This patches all classes loaded
 222         // to date so that they are members of java.base. Once java.base is
 223         // loaded then resources in java.base are available for error messages
 224         // needed from here on.
 225 
 226         long t2 = System.nanoTime();
 227 
 228         ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
 229         if (base == null)
 230             throw new InternalError(JAVA_BASE + " not found");
 231         URI baseUri = base.location().orElse(null);
 232         if (baseUri == null)
 233             throw new InternalError(JAVA_BASE + " does not have a location");
 234         BootLoader.loadModule(base);
 235         Modules.defineModule(null, base.descriptor(), baseUri);
 236 
 237         Counters.add("jdk.module.boot.2.defineBaseTime", t2);
 238 
 239 
 240         // Step 2a: Scan all modules when --validate-modules specified
 241 
 242         if (getAndRemoveProperty("jdk.module.validation") != null) {
 243             int errors = ModulePathValidator.scanAllModules(System.out);
 244             if (errors > 0) {
 245                 fail("Validation of module path failed");
 246             }
 247         }
 248 

 249 
 250         // Step 3: If resolution is needed then create the module finder and
 251         // the set of root modules to resolve.
 252 
 253         long t3 = System.nanoTime();
 254 
 255         ModuleFinder savedModuleFinder = null;
 256         ModuleFinder finder;
 257         Set<String> roots;
 258         if (needResolution) {
 259 
 260             // upgraded modules override the modules in the run-time image
 261             if (upgradeModulePath != null)
 262                 systemModuleFinder = ModuleFinder.compose(upgradeModulePath,
 263                                                           systemModuleFinder);
 264 
 265             // The module finder: [--upgrade-module-path] system [--module-path]
 266             if (appModulePath != null) {
 267                 finder = ModuleFinder.compose(systemModuleFinder, appModulePath);
 268             } else {
 269                 finder = systemModuleFinder;
 270             }
 271 
 272             // The root modules to resolve
 273             roots = new HashSet<>();
 274 


 324                     .forEach(mn -> roots.add(mn));
 325             }
 326 
 327             // If `--add-modules ALL-MODULE-PATH` is specified then all observable
 328             // modules on the application module path will be resolved.
 329             if (appModulePath != null && addAllApplicationModules) {
 330                 ModuleFinder f = finder;  // observable modules
 331                 appModulePath.findAll()
 332                     .stream()
 333                     .map(ModuleReference::descriptor)
 334                     .map(ModuleDescriptor::name)
 335                     .filter(mn -> f.find(mn).isPresent())  // observable
 336                     .forEach(mn -> roots.add(mn));
 337             }
 338         } else {
 339             // no resolution case
 340             finder = systemModuleFinder;
 341             roots = null;
 342         }
 343 
 344         Counters.add("jdk.module.boot.3.optionsAndRootsTime", t3);
 345 
 346         // Step 4: Resolve the root modules, with service binding, to create
 347         // the configuration for the boot layer. If resolution is not needed
 348         // then create the configuration for the boot layer from the
 349         // readability graph created at link time.
 350 
 351         long t4 = System.nanoTime();
 352 
 353         Configuration cf;
 354         if (needResolution) {
 355             cf = Modules.newBootLayerConfiguration(finder, roots, traceOutput);
 356         } else {
 357             if (archivedModuleGraph != null) {
 358                 cf = archivedModuleGraph.configuration();
 359             } else {
 360                 Map<String, Set<String>> map = systemModules.moduleReads();
 361                 cf = JLMA.newConfiguration(systemModuleFinder, map);
 362             }
 363         }
 364 
 365         // check that modules specified to --patch-module are resolved
 366         if (isPatched) {
 367             patcher.patchedModules()
 368                     .stream()
 369                     .filter(mn -> !cf.findModule(mn).isPresent())
 370                     .forEach(mn -> warnUnknownModule(PATCH_MODULE, mn));
 371         }
 372 
 373         Counters.add("jdk.module.boot.4.resolveTime", t4);
 374 
 375 
 376         // Step 5: Map the modules in the configuration to class loaders.
 377         // The static configuration provides the mapping of standard and JDK
 378         // modules to the boot and platform loaders. All other modules (JDK
 379         // tool modules, and both explicit and automatic modules on the
 380         // application module path) are defined to the application class
 381         // loader.
 382 
 383         long t5 = System.nanoTime();
 384 
 385         // mapping of modules to class loaders
 386         Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
 387 
 388         // check that all modules to be mapped to the boot loader will be
 389         // loaded from the runtime image
 390         if (haveModulePath) {
 391             for (ResolvedModule resolvedModule : cf.modules()) {
 392                 ModuleReference mref = resolvedModule.reference();
 393                 String name = mref.descriptor().name();
 394                 ClassLoader cl = clf.apply(name);
 395                 if (cl == null) {
 396                     if (upgradeModulePath != null
 397                             && upgradeModulePath.find(name).isPresent())
 398                         fail(name + ": cannot be loaded from upgrade module path");
 399                     if (!systemModuleFinder.find(name).isPresent())
 400                         fail(name + ": cannot be loaded from application module path");
 401                 }
 402             }
 403         }
 404 
 405         // check for split packages in the modules mapped to the built-in loaders
 406         if (hasSplitPackages || isPatched || haveModulePath) {
 407             checkSplitPackages(cf, clf);
 408         }
 409 
 410         // load/register the modules with the built-in class loaders
 411         loadModules(cf, clf);
 412 
 413         Counters.add("jdk.module.boot.5.loadModulesTime", t5);
 414 
 415 
 416         // Step 6: Define all modules to the VM
 417 
 418         long t6 = System.nanoTime();
 419         ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
 420         Counters.add("jdk.module.boot.6.layerCreateTime", t6);
 421 
 422 
 423         // Step 7: Miscellaneous
 424 
 425         // check incubating status
 426         if (hasIncubatorModules || haveModulePath) {
 427             checkIncubatingStatus(cf);
 428         }
 429 
 430         // --add-reads, --add-exports/--add-opens, and --illegal-access
 431         long t7 = System.nanoTime();
 432         addExtraReads(bootLayer);
 433         boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
 434 
 435         Map<String, Set<String>> concealedPackagesToOpen;
 436         Map<String, Set<String>> exportedPackagesToOpen;
 437         if (archivedModuleGraph != null) {
 438             concealedPackagesToOpen = archivedModuleGraph.concealedPackagesToOpen();
 439             exportedPackagesToOpen = archivedModuleGraph.exportedPackagesToOpen();
 440         } else {
 441             concealedPackagesToOpen = systemModules.concealedPackagesToOpen();
 442             exportedPackagesToOpen = systemModules.exportedPackagesToOpen();
 443         }
 444         addIllegalAccess(upgradeModulePath,
 445                          concealedPackagesToOpen,
 446                          exportedPackagesToOpen,
 447                          bootLayer,
 448                          extraExportsOrOpens);
 449         Counters.add("jdk.module.boot.7.adjustModulesTime", t7);
 450 
 451         // save module finders for later use
 452         if (savedModuleFinder != null) {
 453             unlimitedFinder = new SafeModuleFinder(savedModuleFinder);
 454             if (savedModuleFinder != finder)
 455                 limitedFinder = new SafeModuleFinder(finder);
 456         }
 457 
 458         // Module graph can be archived at CDS dump time. Only allow the
 459         // unnamed module case for now.
 460         if (canArchive && (mainModule == null)) {
 461             ArchivedModuleGraph.archive(mainModule,
 462                                         hasSplitPackages,
 463                                         hasIncubatorModules,
 464                                         systemModuleFinder,
 465                                         cf,
 466                                         concealedPackagesToOpen,
 467                                         exportedPackagesToOpen);
 468         }
 469 
 470         // total time to initialize
 471         Counters.add("jdk.module.boot.totalTime", t0);
 472         Counters.publish();
 473 
 474         return bootLayer;
 475     }
 476 
 477     /**
 478      * Load/register the modules to the built-in class loaders.
 479      */
 480     private static void loadModules(Configuration cf,
 481                                     Function<String, ClassLoader> clf) {
 482         for (ResolvedModule resolvedModule : cf.modules()) {
 483             ModuleReference mref = resolvedModule.reference();
 484             String name = resolvedModule.name();
 485             ClassLoader loader = clf.apply(name);
 486             if (loader == null) {
 487                 // skip java.base as it is already loaded
 488                 if (!name.equals(JAVA_BASE)) {
 489                     BootLoader.loadModule(mref);
 490                 }
 491             } else if (loader instanceof BuiltinClassLoader) {
 492                 ((BuiltinClassLoader) loader).loadModule(mref);


1032             if (nameToModule == null) {
1033                 this.nameToModule = nameToModule = mrefs.stream()
1034                         .collect(Collectors.toMap(m -> m.descriptor().name(),
1035                                                   Function.identity()));
1036             }
1037             return Optional.ofNullable(nameToModule.get(name));
1038         }
1039         @Override
1040         public Set<ModuleReference> findAll() {
1041             return mrefs;
1042         }
1043     }
1044 
1045     /**
1046      * Counters for startup performance analysis.
1047      */
1048     static class Counters {
1049         private static final boolean PUBLISH_COUNTERS;
1050         private static final boolean PRINT_COUNTERS;
1051         private static Map<String, Long> counters;



1052         static {
1053             String s = System.getProperty("jdk.module.boot.usePerfData");
1054             if (s == null) {
1055                 PUBLISH_COUNTERS = false;
1056                 PRINT_COUNTERS = false;
1057             } else {
1058                 PUBLISH_COUNTERS = true;
1059                 PRINT_COUNTERS = s.equals("debug");
1060                 counters = new LinkedHashMap<>();  // preserve insert order
1061             }
1062         }
1063 
1064         /**
1065          * Add a counter










1066          */
1067         static void add(String name, long start) {
1068             if (PUBLISH_COUNTERS || PRINT_COUNTERS) {
1069                 counters.put(name, (System.nanoTime() - start));



1070             }
1071         }
1072 
1073         /**
1074          * Publish the counters to the instrumentation buffer or stdout.
1075          */
1076         static void publish() {
1077             if (PUBLISH_COUNTERS || PRINT_COUNTERS) {

1078                 for (Map.Entry<String, Long> e : counters.entrySet()) {
1079                     String name = e.getKey();
1080                     long value = e.getValue();
1081                     if (PUBLISH_COUNTERS)
1082                         PerfCounter.newPerfCounter(name).set(value);
1083                     if (PRINT_COUNTERS)
1084                         System.out.println(name + " = " + value);
1085                 }




1086             }
1087         }
1088     }
1089 }
   1 /*
   2  * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 123      * Returns the ModuleFinder for the initial configuration.
 124      *
 125      * @apiNote Used to support "{@code java --list-modules}".
 126      */
 127     public static ModuleFinder limitedFinder() {
 128         ModuleFinder finder = limitedFinder;
 129         if (finder == null) {
 130             return unlimitedFinder();
 131         } else {
 132             return finder;
 133         }
 134     }
 135 
 136     /**
 137      * Initialize the module system, returning the boot layer.
 138      *
 139      * @see java.lang.System#initPhase2(boolean, boolean)
 140      */
 141     public static ModuleLayer boot() throws Exception {
 142 
 143         Counters.start();
 144 
 145         // Step 0: Command line options
 146 
 147         ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
 148         ModuleFinder appModulePath = finderFor("jdk.module.path");
 149         boolean isPatched = patcher.hasPatches();
 150 
 151         String mainModule = System.getProperty("jdk.module.main");
 152         Set<String> addModules = addModules();
 153         Set<String> limitModules = limitModules();
 154 
 155         PrintStream traceOutput = null;
 156         String trace = getAndRemoveProperty("jdk.module.showModuleResolution");
 157         if (trace != null && Boolean.parseBoolean(trace))
 158             traceOutput = System.out;
 159 
 160         Counters.add("jdk.module.boot.0.commandLineTime");
 161 
 162         // Step 1: The observable system modules, either all system modules
 163         // or the system modules pre-generated for the initial module (the
 164         // initial module may be the unnamed module). If the system modules
 165         // are pre-generated for the initial module then resolution can be
 166         // skipped.
 167 


 168         SystemModules systemModules = null;
 169         ModuleFinder systemModuleFinder;
 170 
 171         boolean haveModulePath = (appModulePath != null || upgradeModulePath != null);
 172         boolean needResolution = true;
 173         boolean canArchive = false;
 174         boolean hasSplitPackages;
 175         boolean hasIncubatorModules;
 176 
 177         // If the java heap was archived at CDS dump time and the environment
 178         // at dump time matches the current environment then use the archived
 179         // system modules and finder.
 180         ArchivedModuleGraph archivedModuleGraph = ArchivedModuleGraph.get(mainModule);
 181         if (archivedModuleGraph != null
 182                 && !haveModulePath
 183                 && addModules.isEmpty()
 184                 && limitModules.isEmpty()
 185                 && !isPatched) {
 186             systemModuleFinder = archivedModuleGraph.finder();
 187             hasSplitPackages = archivedModuleGraph.hasSplitPackages();


 197             }
 198             if (systemModules == null) {
 199                 // all system modules are observable
 200                 systemModules = SystemModuleFinders.allSystemModules();
 201             }
 202             if (systemModules != null) {
 203                 // images build
 204                 systemModuleFinder = SystemModuleFinders.of(systemModules);
 205             } else {
 206                 // exploded build or testing
 207                 systemModules = new ExplodedSystemModules();
 208                 systemModuleFinder = SystemModuleFinders.ofSystem();
 209             }
 210 
 211             hasSplitPackages = systemModules.hasSplitPackages();
 212             hasIncubatorModules = systemModules.hasIncubatorModules();
 213             // not using the archived module graph - avoid accidental use
 214             archivedModuleGraph = null;
 215         }
 216 
 217         Counters.add("jdk.module.boot.1.systemModulesTime");

 218 
 219         // Step 2: Define and load java.base. This patches all classes loaded
 220         // to date so that they are members of java.base. Once java.base is
 221         // loaded then resources in java.base are available for error messages
 222         // needed from here on.
 223 


 224         ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
 225         if (base == null)
 226             throw new InternalError(JAVA_BASE + " not found");
 227         URI baseUri = base.location().orElse(null);
 228         if (baseUri == null)
 229             throw new InternalError(JAVA_BASE + " does not have a location");
 230         BootLoader.loadModule(base);
 231         Modules.defineModule(null, base.descriptor(), baseUri);
 232 



 233         // Step 2a: Scan all modules when --validate-modules specified
 234 
 235         if (getAndRemoveProperty("jdk.module.validation") != null) {
 236             int errors = ModulePathValidator.scanAllModules(System.out);
 237             if (errors > 0) {
 238                 fail("Validation of module path failed");
 239             }
 240         }
 241 
 242         Counters.add("jdk.module.boot.2.defineBaseTime");
 243 
 244         // Step 3: If resolution is needed then create the module finder and
 245         // the set of root modules to resolve.
 246 


 247         ModuleFinder savedModuleFinder = null;
 248         ModuleFinder finder;
 249         Set<String> roots;
 250         if (needResolution) {
 251 
 252             // upgraded modules override the modules in the run-time image
 253             if (upgradeModulePath != null)
 254                 systemModuleFinder = ModuleFinder.compose(upgradeModulePath,
 255                                                           systemModuleFinder);
 256 
 257             // The module finder: [--upgrade-module-path] system [--module-path]
 258             if (appModulePath != null) {
 259                 finder = ModuleFinder.compose(systemModuleFinder, appModulePath);
 260             } else {
 261                 finder = systemModuleFinder;
 262             }
 263 
 264             // The root modules to resolve
 265             roots = new HashSet<>();
 266 


 316                     .forEach(mn -> roots.add(mn));
 317             }
 318 
 319             // If `--add-modules ALL-MODULE-PATH` is specified then all observable
 320             // modules on the application module path will be resolved.
 321             if (appModulePath != null && addAllApplicationModules) {
 322                 ModuleFinder f = finder;  // observable modules
 323                 appModulePath.findAll()
 324                     .stream()
 325                     .map(ModuleReference::descriptor)
 326                     .map(ModuleDescriptor::name)
 327                     .filter(mn -> f.find(mn).isPresent())  // observable
 328                     .forEach(mn -> roots.add(mn));
 329             }
 330         } else {
 331             // no resolution case
 332             finder = systemModuleFinder;
 333             roots = null;
 334         }
 335 
 336         Counters.add("jdk.module.boot.3.optionsAndRootsTime");
 337 
 338         // Step 4: Resolve the root modules, with service binding, to create
 339         // the configuration for the boot layer. If resolution is not needed
 340         // then create the configuration for the boot layer from the
 341         // readability graph created at link time.
 342 


 343         Configuration cf;
 344         if (needResolution) {
 345             cf = Modules.newBootLayerConfiguration(finder, roots, traceOutput);
 346         } else {
 347             if (archivedModuleGraph != null) {
 348                 cf = archivedModuleGraph.configuration();
 349             } else {
 350                 Map<String, Set<String>> map = systemModules.moduleReads();
 351                 cf = JLMA.newConfiguration(systemModuleFinder, map);
 352             }
 353         }
 354 
 355         // check that modules specified to --patch-module are resolved
 356         if (isPatched) {
 357             patcher.patchedModules()
 358                     .stream()
 359                     .filter(mn -> !cf.findModule(mn).isPresent())
 360                     .forEach(mn -> warnUnknownModule(PATCH_MODULE, mn));
 361         }
 362 
 363         Counters.add("jdk.module.boot.4.resolveTime");

 364 
 365         // Step 5: Map the modules in the configuration to class loaders.
 366         // The static configuration provides the mapping of standard and JDK
 367         // modules to the boot and platform loaders. All other modules (JDK
 368         // tool modules, and both explicit and automatic modules on the
 369         // application module path) are defined to the application class
 370         // loader.
 371 


 372         // mapping of modules to class loaders
 373         Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
 374 
 375         // check that all modules to be mapped to the boot loader will be
 376         // loaded from the runtime image
 377         if (haveModulePath) {
 378             for (ResolvedModule resolvedModule : cf.modules()) {
 379                 ModuleReference mref = resolvedModule.reference();
 380                 String name = mref.descriptor().name();
 381                 ClassLoader cl = clf.apply(name);
 382                 if (cl == null) {
 383                     if (upgradeModulePath != null
 384                             && upgradeModulePath.find(name).isPresent())
 385                         fail(name + ": cannot be loaded from upgrade module path");
 386                     if (!systemModuleFinder.find(name).isPresent())
 387                         fail(name + ": cannot be loaded from application module path");
 388                 }
 389             }
 390         }
 391 
 392         // check for split packages in the modules mapped to the built-in loaders
 393         if (hasSplitPackages || isPatched || haveModulePath) {
 394             checkSplitPackages(cf, clf);
 395         }
 396 
 397         // load/register the modules with the built-in class loaders
 398         loadModules(cf, clf);
 399         Counters.add("jdk.module.boot.5.loadModulesTime");


 400 
 401         // Step 6: Define all modules to the VM
 402 

 403         ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
 404         Counters.add("jdk.module.boot.6.layerCreateTime");

 405 
 406         // Step 7: Miscellaneous
 407 
 408         // check incubating status
 409         if (hasIncubatorModules || haveModulePath) {
 410             checkIncubatingStatus(cf);
 411         }
 412 
 413         // --add-reads, --add-exports/--add-opens, and --illegal-access

 414         addExtraReads(bootLayer);
 415         boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
 416 
 417         Map<String, Set<String>> concealedPackagesToOpen;
 418         Map<String, Set<String>> exportedPackagesToOpen;
 419         if (archivedModuleGraph != null) {
 420             concealedPackagesToOpen = archivedModuleGraph.concealedPackagesToOpen();
 421             exportedPackagesToOpen = archivedModuleGraph.exportedPackagesToOpen();
 422         } else {
 423             concealedPackagesToOpen = systemModules.concealedPackagesToOpen();
 424             exportedPackagesToOpen = systemModules.exportedPackagesToOpen();
 425         }
 426         addIllegalAccess(upgradeModulePath,
 427                          concealedPackagesToOpen,
 428                          exportedPackagesToOpen,
 429                          bootLayer,
 430                          extraExportsOrOpens);
 431         Counters.add("jdk.module.boot.7.adjustModulesTime");
 432 
 433         // save module finders for later use
 434         if (savedModuleFinder != null) {
 435             unlimitedFinder = new SafeModuleFinder(savedModuleFinder);
 436             if (savedModuleFinder != finder)
 437                 limitedFinder = new SafeModuleFinder(finder);
 438         }
 439 
 440         // Module graph can be archived at CDS dump time. Only allow the
 441         // unnamed module case for now.
 442         if (canArchive && (mainModule == null)) {
 443             ArchivedModuleGraph.archive(mainModule,
 444                                         hasSplitPackages,
 445                                         hasIncubatorModules,
 446                                         systemModuleFinder,
 447                                         cf,
 448                                         concealedPackagesToOpen,
 449                                         exportedPackagesToOpen);
 450         }
 451 
 452         // total time to initialize
 453         Counters.publish("jdk.module.boot.totalTime");

 454 
 455         return bootLayer;
 456     }
 457 
 458     /**
 459      * Load/register the modules to the built-in class loaders.
 460      */
 461     private static void loadModules(Configuration cf,
 462                                     Function<String, ClassLoader> clf) {
 463         for (ResolvedModule resolvedModule : cf.modules()) {
 464             ModuleReference mref = resolvedModule.reference();
 465             String name = resolvedModule.name();
 466             ClassLoader loader = clf.apply(name);
 467             if (loader == null) {
 468                 // skip java.base as it is already loaded
 469                 if (!name.equals(JAVA_BASE)) {
 470                     BootLoader.loadModule(mref);
 471                 }
 472             } else if (loader instanceof BuiltinClassLoader) {
 473                 ((BuiltinClassLoader) loader).loadModule(mref);


1013             if (nameToModule == null) {
1014                 this.nameToModule = nameToModule = mrefs.stream()
1015                         .collect(Collectors.toMap(m -> m.descriptor().name(),
1016                                                   Function.identity()));
1017             }
1018             return Optional.ofNullable(nameToModule.get(name));
1019         }
1020         @Override
1021         public Set<ModuleReference> findAll() {
1022             return mrefs;
1023         }
1024     }
1025 
1026     /**
1027      * Counters for startup performance analysis.
1028      */
1029     static class Counters {
1030         private static final boolean PUBLISH_COUNTERS;
1031         private static final boolean PRINT_COUNTERS;
1032         private static Map<String, Long> counters;
1033         private static long startTime;
1034         private static long previousTime;
1035 
1036         static {
1037             String s = System.getProperty("jdk.module.boot.usePerfData");
1038             if (s == null) {
1039                 PUBLISH_COUNTERS = false;
1040                 PRINT_COUNTERS = false;
1041             } else {
1042                 PUBLISH_COUNTERS = true;
1043                 PRINT_COUNTERS = s.equals("debug");
1044                 counters = new LinkedHashMap<>();  // preserve insert order
1045             }
1046         }
1047 
1048         /**
1049          * Start counting time.
1050          */
1051         static void start() {
1052             if (PUBLISH_COUNTERS) {
1053                 startTime = previousTime = System.nanoTime();
1054             }
1055         }
1056 
1057         /**
1058          * Add a counter - storing the time difference between now and the
1059          * previous add or the start.
1060          */
1061         static void add(String name) {
1062             if (PUBLISH_COUNTERS) {
1063                 long current = System.nanoTime();
1064                 long elapsed = current - previousTime;
1065                 previousTime = current;
1066                 counters.put(name, elapsed);
1067             }
1068         }
1069 
1070         /**
1071          * Publish the counters to the instrumentation buffer or stdout.
1072          */
1073         static void publish(String totalTimeName) {
1074             if (PUBLISH_COUNTERS) {
1075                 long currentTime = System.nanoTime();
1076                 for (Map.Entry<String, Long> e : counters.entrySet()) {
1077                     String name = e.getKey();
1078                     long value = e.getValue();

1079                     PerfCounter.newPerfCounter(name).set(value);
1080                     if (PRINT_COUNTERS)
1081                         System.out.println(name + " = " + value);
1082                 }
1083                 long elapsedTotal = currentTime - startTime;
1084                 PerfCounter.newPerfCounter(totalTimeName).set(elapsedTotal);
1085                 if (PRINT_COUNTERS)
1086                     System.out.println(totalTimeName + " = " + elapsedTotal);
1087             }
1088         }
1089     }
1090 }
< prev index next >