< prev index next >

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

Print this page




   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
  23  * questions.
  24  */
  25 
  26 package jdk.internal.module;
  27 
  28 import java.io.File;

  29 import java.io.PrintStream;

  30 import java.lang.module.Configuration;
  31 import java.lang.module.ModuleDescriptor;
  32 import java.lang.module.ModuleFinder;
  33 import java.lang.module.ModuleReference;
  34 import java.lang.module.ResolvedModule;
  35 import java.lang.reflect.Layer;
  36 import java.lang.reflect.Module;
  37 import java.net.URI;

  38 import java.nio.file.Path;
  39 import java.nio.file.Paths;
  40 import java.util.ArrayList;
  41 import java.util.Collections;
  42 import java.util.HashMap;
  43 import java.util.HashSet;
  44 import java.util.List;
  45 import java.util.Map;
  46 import java.util.Optional;
  47 import java.util.Set;
  48 import java.util.function.Function;

  49 
  50 import jdk.internal.loader.BootLoader;
  51 import jdk.internal.loader.BuiltinClassLoader;
  52 import jdk.internal.misc.SharedSecrets;
  53 import jdk.internal.perf.PerfCounter;
  54 
  55 /**
  56  * Initializes/boots the module system.
  57  *
  58  * The {@link #boot() boot} method is called early in the startup to initialize
  59  * the module system. In summary, the boot method creates a Configuration by
  60  * resolving a set of module names specified via the launcher (or equivalent)
  61  * -m and --add-modules options. The modules are located on a module path that
  62  * is constructed from the upgrade module path, system modules, and application
  63  * module path. The Configuration is instantiated as the boot Layer with each
  64  * module in the the configuration defined to one of the built-in class loaders.
  65  */
  66 
  67 public final class ModuleBootstrap {
  68     private ModuleBootstrap() { }


  97     }
  98 
  99     /**
 100      * Returns the ModuleFinder for the initial configuration
 101      */
 102     public static ModuleFinder finder() {
 103         assert initialFinder != null;
 104         return initialFinder;
 105     }
 106 
 107     /**
 108      * Initialize the module system, returning the boot Layer.
 109      *
 110      * @see java.lang.System#initPhase2()
 111      */
 112     public static Layer boot() {
 113 
 114         long t0 = System.nanoTime();
 115 
 116         // system modules (may be patched)
 117         ModuleFinder systemModules = ModuleFinder.ofSystem();





 118 
 119         PerfCounters.systemModulesTime.addElapsedTimeFrom(t0);
 120 
 121 
 122         long t1 = System.nanoTime();
 123 
 124         // Once we have the system modules then we define the base module to
 125         // the VM. We do this here so that java.base is defined as early as
 126         // possible and also that resources in the base module can be located
 127         // for error messages that may happen from here on.
 128         ModuleReference base = systemModules.find(JAVA_BASE).orElse(null);
 129         if (base == null)
 130             throw new InternalError(JAVA_BASE + " not found");
 131         URI baseUri = base.location().orElse(null);
 132         if (baseUri == null)
 133             throw new InternalError(JAVA_BASE + " does not have a location");
 134         BootLoader.loadModule(base);
 135         Modules.defineModule(null, base.descriptor(), baseUri);
 136 
 137         PerfCounters.defineBaseTime.addElapsedTimeFrom(t1);


 258         PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t2);
 259 
 260 
 261         long t3 = System.nanoTime();
 262 
 263         // determine if post resolution checks are needed
 264         boolean needPostResolutionChecks = true;
 265         if (baseUri.getScheme().equals("jrt")   // toLowerCase not needed here
 266                 && (upgradeModulePath == null)
 267                 && (appModulePath == null)
 268                 && (patcher.isEmpty())) {
 269             needPostResolutionChecks = false;
 270         }
 271 
 272         PrintStream traceOutput = null;
 273         if (Boolean.getBoolean("jdk.launcher.traceResolver"))
 274             traceOutput = System.out;
 275 
 276         // run the resolver to create the configuration
 277         Configuration cf = SharedSecrets.getJavaLangModuleAccess()
 278                 .resolveRequiresAndUses(finder,
 279                                         roots,
 280                                         needPostResolutionChecks,
 281                                         traceOutput);
 282 
 283         // time to create configuration
 284         PerfCounters.resolveTime.addElapsedTimeFrom(t3);
 285 
 286         // check module names and incubating status
 287         checkModuleNamesAndStatus(cf);
 288 
 289         // mapping of modules to class loaders
 290         Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
 291 
 292         // check that all modules to be mapped to the boot loader will be
 293         // loaded from the runtime image
 294         if (needPostResolutionChecks) {
 295             for (ResolvedModule resolvedModule : cf.modules()) {
 296                 ModuleReference mref = resolvedModule.reference();
 297                 String name = mref.descriptor().name();
 298                 ClassLoader cl = clf.apply(name);


 363         addExtraExportsAndOpens(bootLayer);
 364 
 365         // total time to initialize
 366         PerfCounters.bootstrapTime.addElapsedTimeFrom(t0);
 367 
 368         // remember the ModuleFinder
 369         initialFinder = finder;
 370 
 371         return bootLayer;
 372     }
 373 
 374     /**
 375      * Returns a ModuleFinder that limits observability to the given root
 376      * modules, their transitive dependences, plus a set of other modules.
 377      */
 378     private static ModuleFinder limitFinder(ModuleFinder finder,
 379                                             Set<String> roots,
 380                                             Set<String> otherMods)
 381     {
 382         // resolve all root modules
 383         Configuration cf = Configuration.empty()
 384                 .resolveRequires(finder,
 385                                  ModuleFinder.of(),
 386                                  roots);
 387 
 388         // module name -> reference
 389         Map<String, ModuleReference> map = new HashMap<>();
 390 
 391         // root modules and their transitive dependences
 392         cf.modules().stream()
 393             .map(ResolvedModule::reference)
 394             .forEach(mref -> map.put(mref.descriptor().name(), mref));
 395 
 396         // additional modules
 397         otherMods.stream()
 398             .map(finder::find)
 399             .flatMap(Optional::stream)
 400             .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref));
 401 
 402         // set of modules that are observable
 403         Set<ModuleReference> mrefs = new HashSet<>(map.values());
 404 


 511 
 512     /**
 513      * Process the --add-exports and --add-opens options to export/open
 514      * additional packages specified on the command-line.
 515      */
 516     private static void addExtraExportsAndOpens(Layer bootLayer) {
 517 
 518         // --add-exports
 519         String prefix = "jdk.module.addexports.";
 520         Map<String, List<String>> extraExports = decode(prefix);
 521         if (!extraExports.isEmpty()) {
 522             addExtraExportsOrOpens(bootLayer, extraExports, false);
 523         }
 524 
 525         // --add-opens
 526         prefix = "jdk.module.addopens.";
 527         Map<String, List<String>> extraOpens = decode(prefix);
 528         if (!extraOpens.isEmpty()) {
 529             addExtraExportsOrOpens(bootLayer, extraOpens, true);
 530         }























 531     }
 532 

















 533     private static void addExtraExportsOrOpens(Layer bootLayer,
 534                                                Map<String, List<String>> map,
 535                                                boolean opens)
 536     {
 537         String option = opens ? ADD_OPENS : ADD_EXPORTS;
 538         for (Map.Entry<String, List<String>> e : map.entrySet()) {
 539 
 540             // the key is $MODULE/$PACKAGE
 541             String key = e.getKey();
 542             String[] s = key.split("/");
 543             if (s.length != 2)
 544                 fail(unableToParse(option,  "<module>/<package>", key));
 545 
 546             String mn = s[0];
 547             String pn = s[1];
 548             if (mn.isEmpty() || pn.isEmpty())
 549                 fail(unableToParse(option,  "<module>/<package>", key));
 550 
 551             // The exporting module is in the boot layer
 552             Module m;




   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
  23  * questions.
  24  */
  25 
  26 package jdk.internal.module;
  27 
  28 import java.io.File;
  29 import java.io.IOException;
  30 import java.io.PrintStream;
  31 import java.io.UncheckedIOException;
  32 import java.lang.module.Configuration;
  33 import java.lang.module.ModuleDescriptor;
  34 import java.lang.module.ModuleFinder;
  35 import java.lang.module.ModuleReference;
  36 import java.lang.module.ResolvedModule;
  37 import java.lang.reflect.Layer;
  38 import java.lang.reflect.Module;
  39 import java.net.URI;
  40 import java.nio.file.Files;
  41 import java.nio.file.Path;
  42 import java.nio.file.Paths;
  43 import java.util.ArrayList;
  44 import java.util.Collections;
  45 import java.util.HashMap;
  46 import java.util.HashSet;
  47 import java.util.List;
  48 import java.util.Map;
  49 import java.util.Optional;
  50 import java.util.Set;
  51 import java.util.function.Function;
  52 import java.util.stream.Stream;
  53 
  54 import jdk.internal.loader.BootLoader;
  55 import jdk.internal.loader.BuiltinClassLoader;
  56 import jdk.internal.misc.SharedSecrets;
  57 import jdk.internal.perf.PerfCounter;
  58 
  59 /**
  60  * Initializes/boots the module system.
  61  *
  62  * The {@link #boot() boot} method is called early in the startup to initialize
  63  * the module system. In summary, the boot method creates a Configuration by
  64  * resolving a set of module names specified via the launcher (or equivalent)
  65  * -m and --add-modules options. The modules are located on a module path that
  66  * is constructed from the upgrade module path, system modules, and application
  67  * module path. The Configuration is instantiated as the boot Layer with each
  68  * module in the the configuration defined to one of the built-in class loaders.
  69  */
  70 
  71 public final class ModuleBootstrap {
  72     private ModuleBootstrap() { }


 101     }
 102 
 103     /**
 104      * Returns the ModuleFinder for the initial configuration
 105      */
 106     public static ModuleFinder finder() {
 107         assert initialFinder != null;
 108         return initialFinder;
 109     }
 110 
 111     /**
 112      * Initialize the module system, returning the boot Layer.
 113      *
 114      * @see java.lang.System#initPhase2()
 115      */
 116     public static Layer boot() {
 117 
 118         long t0 = System.nanoTime();
 119 
 120         // system modules (may be patched)
 121         ModuleFinder systemModules;
 122         if (SystemModules.MODULE_NAMES.length > 0) {
 123             systemModules = SystemModuleFinder.getInstance();
 124         } else {
 125             systemModules = ModuleFinder.ofSystem();
 126         }
 127 
 128         PerfCounters.systemModulesTime.addElapsedTimeFrom(t0);
 129 
 130 
 131         long t1 = System.nanoTime();
 132 
 133         // Once we have the system modules then we define the base module to
 134         // the VM. We do this here so that java.base is defined as early as
 135         // possible and also that resources in the base module can be located
 136         // for error messages that may happen from here on.
 137         ModuleReference base = systemModules.find(JAVA_BASE).orElse(null);
 138         if (base == null)
 139             throw new InternalError(JAVA_BASE + " not found");
 140         URI baseUri = base.location().orElse(null);
 141         if (baseUri == null)
 142             throw new InternalError(JAVA_BASE + " does not have a location");
 143         BootLoader.loadModule(base);
 144         Modules.defineModule(null, base.descriptor(), baseUri);
 145 
 146         PerfCounters.defineBaseTime.addElapsedTimeFrom(t1);


 267         PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t2);
 268 
 269 
 270         long t3 = System.nanoTime();
 271 
 272         // determine if post resolution checks are needed
 273         boolean needPostResolutionChecks = true;
 274         if (baseUri.getScheme().equals("jrt")   // toLowerCase not needed here
 275                 && (upgradeModulePath == null)
 276                 && (appModulePath == null)
 277                 && (patcher.isEmpty())) {
 278             needPostResolutionChecks = false;
 279         }
 280 
 281         PrintStream traceOutput = null;
 282         if (Boolean.getBoolean("jdk.launcher.traceResolver"))
 283             traceOutput = System.out;
 284 
 285         // run the resolver to create the configuration
 286         Configuration cf = SharedSecrets.getJavaLangModuleAccess()
 287                 .resolveAndBind(finder,
 288                                 roots,
 289                                 needPostResolutionChecks,
 290                                 traceOutput);
 291 
 292         // time to create configuration
 293         PerfCounters.resolveTime.addElapsedTimeFrom(t3);
 294 
 295         // check module names and incubating status
 296         checkModuleNamesAndStatus(cf);
 297 
 298         // mapping of modules to class loaders
 299         Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
 300 
 301         // check that all modules to be mapped to the boot loader will be
 302         // loaded from the runtime image
 303         if (needPostResolutionChecks) {
 304             for (ResolvedModule resolvedModule : cf.modules()) {
 305                 ModuleReference mref = resolvedModule.reference();
 306                 String name = mref.descriptor().name();
 307                 ClassLoader cl = clf.apply(name);


 372         addExtraExportsAndOpens(bootLayer);
 373 
 374         // total time to initialize
 375         PerfCounters.bootstrapTime.addElapsedTimeFrom(t0);
 376 
 377         // remember the ModuleFinder
 378         initialFinder = finder;
 379 
 380         return bootLayer;
 381     }
 382 
 383     /**
 384      * Returns a ModuleFinder that limits observability to the given root
 385      * modules, their transitive dependences, plus a set of other modules.
 386      */
 387     private static ModuleFinder limitFinder(ModuleFinder finder,
 388                                             Set<String> roots,
 389                                             Set<String> otherMods)
 390     {
 391         // resolve all root modules
 392         Configuration cf = Configuration.empty().resolve(finder,

 393                                                          ModuleFinder.of(),
 394                                                          roots);
 395 
 396         // module name -> reference
 397         Map<String, ModuleReference> map = new HashMap<>();
 398 
 399         // root modules and their transitive dependences
 400         cf.modules().stream()
 401             .map(ResolvedModule::reference)
 402             .forEach(mref -> map.put(mref.descriptor().name(), mref));
 403 
 404         // additional modules
 405         otherMods.stream()
 406             .map(finder::find)
 407             .flatMap(Optional::stream)
 408             .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref));
 409 
 410         // set of modules that are observable
 411         Set<ModuleReference> mrefs = new HashSet<>(map.values());
 412 


 519 
 520     /**
 521      * Process the --add-exports and --add-opens options to export/open
 522      * additional packages specified on the command-line.
 523      */
 524     private static void addExtraExportsAndOpens(Layer bootLayer) {
 525 
 526         // --add-exports
 527         String prefix = "jdk.module.addexports.";
 528         Map<String, List<String>> extraExports = decode(prefix);
 529         if (!extraExports.isEmpty()) {
 530             addExtraExportsOrOpens(bootLayer, extraExports, false);
 531         }
 532 
 533         // --add-opens
 534         prefix = "jdk.module.addopens.";
 535         Map<String, List<String>> extraOpens = decode(prefix);
 536         if (!extraOpens.isEmpty()) {
 537             addExtraExportsOrOpens(bootLayer, extraOpens, true);
 538         }
 539 
 540         // DEBUG_ADD_OPENS is for debugging purposes only
 541         String home = System.getProperty("java.home");
 542         Path file = Paths.get(home, "conf", "DEBUG_ADD_OPENS");
 543         if (Files.exists(file)) {
 544             warn(file + " detected; may break encapsulation");
 545             try (Stream<String> lines = Files.lines(file)) {
 546                 lines.map(line -> line.trim())
 547                     .filter(line -> (!line.isEmpty() && !line.startsWith("#")))
 548                     .forEach(line -> {
 549                         String[] s = line.split("/");
 550                         if (s.length != 2) {
 551                             fail("Unable to parse as <module>/<package>: " + line);
 552                         } else {
 553                             String mn = s[0];
 554                             String pkg = s[1];
 555                             openPackage(bootLayer, mn, pkg);
 556                         }
 557                     });
 558             } catch (IOException ioe) {
 559                 throw new UncheckedIOException(ioe);
 560             }
 561         }
 562     }
 563 
 564     private static void openPackage(Layer bootLayer, String mn, String pkg) {
 565         if (mn.equals("ALL-RESOLVED") && pkg.equals("ALL-PACKAGES")) {
 566             bootLayer.modules().stream().forEach(m ->
 567                 m.getDescriptor().packages().forEach(pn -> openPackage(m, pn)));
 568         } else {
 569             bootLayer.findModule(mn)
 570                      .filter(m -> m.getDescriptor().packages().contains(pkg))
 571                      .ifPresent(m -> openPackage(m, pkg));
 572         }
 573     }
 574 
 575     private static void openPackage(Module m, String pn) {
 576         Modules.addOpensToAllUnnamed(m, pn);
 577         warn("Opened for deep reflection: " + m.getName()  + "/" + pn);
 578     }
 579 
 580 
 581     private static void addExtraExportsOrOpens(Layer bootLayer,
 582                                                Map<String, List<String>> map,
 583                                                boolean opens)
 584     {
 585         String option = opens ? ADD_OPENS : ADD_EXPORTS;
 586         for (Map.Entry<String, List<String>> e : map.entrySet()) {
 587 
 588             // the key is $MODULE/$PACKAGE
 589             String key = e.getKey();
 590             String[] s = key.split("/");
 591             if (s.length != 2)
 592                 fail(unableToParse(option,  "<module>/<package>", key));
 593 
 594             String mn = s[0];
 595             String pn = s[1];
 596             if (mn.isEmpty() || pn.isEmpty())
 597                 fail(unableToParse(option,  "<module>/<package>", key));
 598 
 599             // The exporting module is in the boot layer
 600             Module m;


< prev index next >