< prev index next >

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

Print this page
rev 52800 : 8214858: Improve module graph archiving
Reviewed-by: alanb


 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 
 176         // If the java heap was archived at CDS dump time and the environment
 177         // at dump time matches the current environment then use the archived
 178         // system modules and finder.
 179         ArchivedModuleGraph archivedModuleGraph = ArchivedModuleGraph.get(mainModule);
 180         if (archivedModuleGraph != null
 181                 && !haveModulePath
 182                 && addModules.isEmpty()
 183                 && limitModules.isEmpty()
 184                 && !isPatched) {
 185             systemModules = archivedModuleGraph.systemModules();
 186             systemModuleFinder = archivedModuleGraph.finder();


 187             needResolution = (traceOutput != null);
 188         } else {
 189             if (!haveModulePath && addModules.isEmpty() && limitModules.isEmpty()) {
 190                 systemModules = SystemModuleFinders.systemModules(mainModule);
 191                 if (systemModules != null && !isPatched) {
 192                     needResolution = (traceOutput != null);
 193                     canArchive = true;
 194                 }
 195             }
 196             if (systemModules == null) {
 197                 // all system modules are observable
 198                 systemModules = SystemModuleFinders.allSystemModules();
 199             }
 200             if (systemModules != null) {
 201                 // images build
 202                 systemModuleFinder = SystemModuleFinders.of(systemModules);
 203             } else {
 204                 // exploded build or testing
 205                 systemModules = new ExplodedSystemModules();
 206                 systemModuleFinder = SystemModuleFinders.ofSystem();
 207             }





 208         }
 209 
 210         Counters.add("jdk.module.boot.1.systemModulesTime", t1);
 211 
 212 
 213         // Step 2: Define and load java.base. This patches all classes loaded
 214         // to date so that they are members of java.base. Once java.base is
 215         // loaded then resources in java.base are available for error messages
 216         // needed from here on.
 217 
 218         long t2 = System.nanoTime();
 219 
 220         ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
 221         if (base == null)
 222             throw new InternalError(JAVA_BASE + " not found");
 223         URI baseUri = base.location().orElse(null);
 224         if (baseUri == null)
 225             throw new InternalError(JAVA_BASE + " does not have a location");
 226         BootLoader.loadModule(base);
 227         Modules.defineModule(null, base.descriptor(), baseUri);


 378         Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
 379 
 380         // check that all modules to be mapped to the boot loader will be
 381         // loaded from the runtime image
 382         if (haveModulePath) {
 383             for (ResolvedModule resolvedModule : cf.modules()) {
 384                 ModuleReference mref = resolvedModule.reference();
 385                 String name = mref.descriptor().name();
 386                 ClassLoader cl = clf.apply(name);
 387                 if (cl == null) {
 388                     if (upgradeModulePath != null
 389                             && upgradeModulePath.find(name).isPresent())
 390                         fail(name + ": cannot be loaded from upgrade module path");
 391                     if (!systemModuleFinder.find(name).isPresent())
 392                         fail(name + ": cannot be loaded from application module path");
 393                 }
 394             }
 395         }
 396 
 397         // check for split packages in the modules mapped to the built-in loaders
 398         if (systemModules.hasSplitPackages() || isPatched || haveModulePath) {
 399             checkSplitPackages(cf, clf);
 400         }
 401 
 402         // load/register the modules with the built-in class loaders
 403         loadModules(cf, clf);
 404 
 405         Counters.add("jdk.module.boot.5.loadModulesTime", t5);
 406 
 407 
 408         // Step 6: Define all modules to the VM
 409 
 410         long t6 = System.nanoTime();
 411         ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
 412         Counters.add("jdk.module.boot.6.layerCreateTime", t6);
 413 
 414 
 415         // Step 7: Miscellaneous
 416 
 417         // check incubating status
 418         if (systemModules.hasIncubatorModules() || haveModulePath) {
 419             checkIncubatingStatus(cf);
 420         }
 421 
 422         // --add-reads, --add-exports/--add-opens, and --illegal-access
 423         long t7 = System.nanoTime();
 424         addExtraReads(bootLayer);
 425         boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
 426         addIllegalAccess(upgradeModulePath, systemModules, bootLayer, extraExportsOrOpens);














 427         Counters.add("jdk.module.boot.7.adjustModulesTime", t7);
 428 
 429         // save module finders for later use
 430         if (savedModuleFinder != null) {
 431             unlimitedFinder = new SafeModuleFinder(savedModuleFinder);
 432             if (savedModuleFinder != finder)
 433                 limitedFinder = new SafeModuleFinder(finder);
 434         }
 435 
 436         // Module graph can be archived at CDS dump time. Only allow the
 437         // unnamed module case for now.
 438         if (canArchive && (mainModule == null)) {
 439             ArchivedModuleGraph.archive(mainModule, systemModules,
 440                                         systemModuleFinder, cf);





 441         }
 442 
 443         // total time to initialize
 444         Counters.add("jdk.module.boot.totalTime", t0);
 445         Counters.publish();
 446 
 447         return bootLayer;
 448     }
 449 
 450     /**
 451      * Load/register the modules to the built-in class loaders.
 452      */
 453     private static void loadModules(Configuration cf,
 454                                     Function<String, ClassLoader> clf) {
 455         for (ResolvedModule resolvedModule : cf.modules()) {
 456             ModuleReference mref = resolvedModule.reference();
 457             String name = resolvedModule.name();
 458             ClassLoader loader = clf.apply(name);
 459             if (loader == null) {
 460                 // skip java.base as it is already loaded


 721                     } else {
 722                         Modules.addExportsToAllUnnamed(m, pn);
 723                     }
 724                 } else {
 725                     if (opens) {
 726                         Modules.addOpens(m, pn, other);
 727                     } else {
 728                         Modules.addExports(m, pn, other);
 729                     }
 730                 }
 731 
 732             }
 733         }
 734     }
 735 
 736     /**
 737      * Process the --illegal-access option (and its default) to open packages
 738      * of system modules in the boot layer to code in unnamed modules.
 739      */
 740     private static void addIllegalAccess(ModuleFinder upgradeModulePath,
 741                                          SystemModules systemModules,

 742                                          ModuleLayer bootLayer,
 743                                          boolean extraExportsOrOpens) {
 744         String value = getAndRemoveProperty("jdk.module.illegalAccess");
 745         IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT;
 746         if (value != null) {
 747             switch (value) {
 748                 case "deny":
 749                     return;
 750                 case "permit":
 751                     break;
 752                 case "warn":
 753                     mode = IllegalAccessLogger.Mode.WARN;
 754                     break;
 755                 case "debug":
 756                     mode = IllegalAccessLogger.Mode.DEBUG;
 757                     break;
 758                 default:
 759                     fail("Value specified to --illegal-access not recognized:"
 760                             + " '" + value + "'");
 761                     return;
 762             }
 763         }
 764         IllegalAccessLogger.Builder builder
 765             = new IllegalAccessLogger.Builder(mode, System.err);
 766 
 767         Map<String, Set<String>> map1 = systemModules.concealedPackagesToOpen();
 768         Map<String, Set<String>> map2 = systemModules.exportedPackagesToOpen();
 769         if (map1.isEmpty() && map2.isEmpty()) {
 770             // need to generate (exploded build)
 771             IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
 772             map1 = maps.concealedPackagesToOpen();
 773             map2 = maps.exportedPackagesToOpen();
 774         }
 775 
 776         // open specific packages in the system modules
 777         for (Module m : bootLayer.modules()) {
 778             ModuleDescriptor descriptor = m.getDescriptor();
 779             String name = m.getName();
 780 
 781             // skip open modules
 782             if (descriptor.isOpen()) {
 783                 continue;
 784             }
 785 
 786             // skip modules loaded from the upgrade module path
 787             if (upgradeModulePath != null
 788                 && upgradeModulePath.find(name).isPresent()) {
 789                 continue;
 790             }
 791 
 792             Set<String> concealedPackages = map1.getOrDefault(name, Set.of());
 793             Set<String> exportedPackages = map2.getOrDefault(name, Set.of());
 794 
 795             // refresh the set of concealed and exported packages if needed
 796             if (extraExportsOrOpens) {
 797                 concealedPackages = new HashSet<>(concealedPackages);
 798                 exportedPackages = new HashSet<>(exportedPackages);
 799                 Iterator<String> iterator = concealedPackages.iterator();
 800                 while (iterator.hasNext()) {
 801                     String pn = iterator.next();
 802                     if (m.isExported(pn, BootLoader.getUnnamedModule())) {
 803                         // concealed package is exported to ALL-UNNAMED
 804                         iterator.remove();
 805                         exportedPackages.add(pn);
 806                     }
 807                 }
 808                 iterator = exportedPackages.iterator();
 809                 while (iterator.hasNext()) {
 810                     String pn = iterator.next();
 811                     if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
 812                         // exported package is opened to ALL-UNNAMED
 813                         iterator.remove();




 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();
 189             hasIncubatorModules = archivedModuleGraph.hasIncubatorModules();
 190             needResolution = (traceOutput != null);
 191         } else {
 192             if (!haveModulePath && addModules.isEmpty() && limitModules.isEmpty()) {
 193                 systemModules = SystemModuleFinders.systemModules(mainModule);
 194                 if (systemModules != null && !isPatched) {
 195                     needResolution = (traceOutput != null);
 196                     canArchive = true;
 197                 }
 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);


 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


 748                     } else {
 749                         Modules.addExportsToAllUnnamed(m, pn);
 750                     }
 751                 } else {
 752                     if (opens) {
 753                         Modules.addOpens(m, pn, other);
 754                     } else {
 755                         Modules.addExports(m, pn, other);
 756                     }
 757                 }
 758 
 759             }
 760         }
 761     }
 762 
 763     /**
 764      * Process the --illegal-access option (and its default) to open packages
 765      * of system modules in the boot layer to code in unnamed modules.
 766      */
 767     private static void addIllegalAccess(ModuleFinder upgradeModulePath,
 768                                          Map<String, Set<String>> concealedPackagesToOpen,
 769                                          Map<String, Set<String>> exportedPackagesToOpen,
 770                                          ModuleLayer bootLayer,
 771                                          boolean extraExportsOrOpens) {
 772         String value = getAndRemoveProperty("jdk.module.illegalAccess");
 773         IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT;
 774         if (value != null) {
 775             switch (value) {
 776                 case "deny":
 777                     return;
 778                 case "permit":
 779                     break;
 780                 case "warn":
 781                     mode = IllegalAccessLogger.Mode.WARN;
 782                     break;
 783                 case "debug":
 784                     mode = IllegalAccessLogger.Mode.DEBUG;
 785                     break;
 786                 default:
 787                     fail("Value specified to --illegal-access not recognized:"
 788                             + " '" + value + "'");
 789                     return;
 790             }
 791         }
 792         IllegalAccessLogger.Builder builder
 793             = new IllegalAccessLogger.Builder(mode, System.err);
 794 
 795         if (concealedPackagesToOpen.isEmpty() && exportedPackagesToOpen.isEmpty()) {


 796             // need to generate (exploded build)
 797             IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
 798             concealedPackagesToOpen = maps.concealedPackagesToOpen();
 799             exportedPackagesToOpen = maps.exportedPackagesToOpen();
 800         }
 801 
 802         // open specific packages in the system modules
 803         for (Module m : bootLayer.modules()) {
 804             ModuleDescriptor descriptor = m.getDescriptor();
 805             String name = m.getName();
 806 
 807             // skip open modules
 808             if (descriptor.isOpen()) {
 809                 continue;
 810             }
 811 
 812             // skip modules loaded from the upgrade module path
 813             if (upgradeModulePath != null
 814                 && upgradeModulePath.find(name).isPresent()) {
 815                 continue;
 816             }
 817 
 818             Set<String> concealedPackages = concealedPackagesToOpen.getOrDefault(name, Set.of());
 819             Set<String> exportedPackages = exportedPackagesToOpen.getOrDefault(name, Set.of());
 820 
 821             // refresh the set of concealed and exported packages if needed
 822             if (extraExportsOrOpens) {
 823                 concealedPackages = new HashSet<>(concealedPackages);
 824                 exportedPackages = new HashSet<>(exportedPackages);
 825                 Iterator<String> iterator = concealedPackages.iterator();
 826                 while (iterator.hasNext()) {
 827                     String pn = iterator.next();
 828                     if (m.isExported(pn, BootLoader.getUnnamedModule())) {
 829                         // concealed package is exported to ALL-UNNAMED
 830                         iterator.remove();
 831                         exportedPackages.add(pn);
 832                     }
 833                 }
 834                 iterator = exportedPackages.iterator();
 835                 while (iterator.hasNext()) {
 836                     String pn = iterator.next();
 837                     if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
 838                         // exported package is opened to ALL-UNNAMED
 839                         iterator.remove();


< prev index next >