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); 299 if (cl == null) { 300 301 if (upgradeModulePath != null 302 && upgradeModulePath.find(name).isPresent()) 303 fail(name + ": cannot be loaded from upgrade module path"); 304 305 if (!systemModules.find(name).isPresent()) 306 fail(name + ": cannot be loaded from application module path"); 307 } 308 } 309 } 310 311 312 long t4 = System.nanoTime(); 313 314 // define modules to VM/runtime 315 Layer bootLayer = Layer.empty().defineModules(cf, clf); 316 317 PerfCounters.layerCreateTime.addElapsedTimeFrom(t4); 318 319 320 long t5 = System.nanoTime(); 321 322 // define the module to its class loader, except java.base 323 for (ResolvedModule resolvedModule : cf.modules()) { 324 ModuleReference mref = resolvedModule.reference(); 325 String name = mref.descriptor().name(); 326 ClassLoader cl = clf.apply(name); 327 if (cl == null) { 328 if (!name.equals(JAVA_BASE)) BootLoader.loadModule(mref); 447 return modules; 448 } 449 450 /** 451 * Process the --add-reads options to add any additional read edges that 452 * are specified on the command-line. 453 */ 454 private static void addExtraReads(Layer bootLayer) { 455 456 // decode the command line options 457 Map<String, List<String>> map = decode("jdk.module.addreads."); 458 if (map.isEmpty()) 459 return; 460 461 for (Map.Entry<String, List<String>> e : map.entrySet()) { 462 463 // the key is $MODULE 464 String mn = e.getKey(); 465 Optional<Module> om = bootLayer.findModule(mn); 466 if (!om.isPresent()) { 467 warn("Unknown module: " + mn); 468 continue; 469 } 470 Module m = om.get(); 471 472 // the value is the set of other modules (by name) 473 for (String name : e.getValue()) { 474 if (ALL_UNNAMED.equals(name)) { 475 Modules.addReadsAllUnnamed(m); 476 } else { 477 om = bootLayer.findModule(name); 478 if (om.isPresent()) { 479 Modules.addReads(m, om.get()); 480 } else { 481 warn("Unknown module: " + name); 482 } 483 } 484 } 485 } 486 } 487 488 /** 489 * Process the --add-exports and --add-opens options to export/open 490 * additional packages specified on the command-line. 491 */ 492 private static void addExtraExportsAndOpens(Layer bootLayer) { 493 494 // --add-exports 495 String prefix = "jdk.module.addexports."; 496 Map<String, List<String>> extraExports = decode(prefix); 497 if (!extraExports.isEmpty()) { 498 addExtraExportsOrOpens(bootLayer, extraExports, false); 499 } 500 501 // --add-opens 502 prefix = "jdk.module.addopens."; 503 Map<String, List<String>> extraOpens = decode(prefix); 504 if (!extraOpens.isEmpty()) { 505 addExtraExportsOrOpens(bootLayer, extraOpens, true); 506 } 507 } 508 509 private static void addExtraExportsOrOpens(Layer bootLayer, 510 Map<String, List<String>> map, 511 boolean opens) 512 { 513 for (Map.Entry<String, List<String>> e : map.entrySet()) { 514 515 // the key is $MODULE/$PACKAGE 516 String key = e.getKey(); 517 String[] s = key.split("/"); 518 if (s.length != 2) 519 fail("Unable to parse as <module>/<package>: " + key); 520 521 String mn = s[0]; 522 String pn = s[1]; 523 if (mn.isEmpty() || pn.isEmpty()) 524 fail("Module and package name must be specified: " + key); 525 526 // The exporting module is in the boot layer 527 Module m; 528 Optional<Module> om = bootLayer.findModule(mn); 529 if (!om.isPresent()) { 530 warn("Unknown module: " + mn); 531 continue; 532 } 533 534 m = om.get(); 535 536 if (!m.getDescriptor().packages().contains(pn)) { 537 warn("package " + pn + " not in " + mn); 538 continue; 539 } 540 541 // the value is the set of modules to export to (by name) 542 for (String name : e.getValue()) { 543 boolean allUnnamed = false; 544 Module other = null; 545 if (ALL_UNNAMED.equals(name)) { 546 allUnnamed = true; 547 } else { 548 om = bootLayer.findModule(name); 549 if (om.isPresent()) { 550 other = om.get(); 551 } else { 552 warn("Unknown module: " + name); 553 continue; 554 } 555 } 556 if (allUnnamed) { 557 if (opens) { 558 Modules.addOpensToAllUnnamed(m, pn); 559 } else { 560 Modules.addExportsToAllUnnamed(m, pn); 561 } 562 } else { 563 if (opens) { 564 Modules.addOpens(m, pn, other); 565 } else { 566 Modules.addExports(m, pn, other); 567 } 568 } 569 570 } 571 } 572 } 576 * --patch-modules options that are encoded in system properties. 577 * 578 * @param prefix the system property prefix 579 * @praam regex the regex for splitting the RHS of the option value 580 */ 581 private static Map<String, List<String>> decode(String prefix, 582 String regex, 583 boolean allowDuplicates) { 584 int index = 0; 585 // the system property is removed after decoding 586 String value = getAndRemoveProperty(prefix + index); 587 if (value == null) 588 return Collections.emptyMap(); 589 590 Map<String, List<String>> map = new HashMap<>(); 591 592 while (value != null) { 593 594 int pos = value.indexOf('='); 595 if (pos == -1) 596 fail("Unable to parse as <module>=<value>: " + value); 597 if (pos == 0) 598 fail("Missing module name in: " + value); 599 600 // key is <module> or <module>/<package> 601 String key = value.substring(0, pos); 602 603 String rhs = value.substring(pos+1); 604 if (rhs.isEmpty()) 605 fail("Unable to parse as <module>=<value>: " + value); 606 607 // value is <module>(,<module>)* or <file>(<pathsep><file>)* 608 if (!allowDuplicates && map.containsKey(key)) 609 fail(key + " specified more than once"); 610 List<String> values = map.computeIfAbsent(key, k -> new ArrayList<>()); 611 for (String s : rhs.split(regex)) { 612 if (s.length() > 0) values.add(s); 613 } 614 615 index++; 616 value = getAndRemoveProperty(prefix + index); 617 } 618 619 return map; 620 } 621 622 /** 623 * Decodes the values of --add-reads, -add-exports or --add-opens 624 * which use the "," to separate the RHS of the option value. 625 */ 626 private static Map<String, List<String>> decode(String prefix) { 627 return decode(prefix, ",", true); 628 } 629 630 /** 631 * Gets and remove the named system property 632 */ 633 private static String getAndRemoveProperty(String key) { 655 } else { 656 incubating += ", " + mn; 657 } 658 } 659 } 660 if (incubating != null) 661 warn("Using incubator modules: " + incubating); 662 } 663 664 /** 665 * Throws a RuntimeException with the given message 666 */ 667 static void fail(String m) { 668 throw new RuntimeException(m); 669 } 670 671 static void warn(String m) { 672 System.err.println("WARNING: " + m); 673 } 674 675 static class PerfCounters { 676 677 static PerfCounter systemModulesTime 678 = PerfCounter.newPerfCounter("jdk.module.bootstrap.systemModulesTime"); 679 static PerfCounter defineBaseTime 680 = PerfCounter.newPerfCounter("jdk.module.bootstrap.defineBaseTime"); 681 static PerfCounter optionsAndRootsTime 682 = PerfCounter.newPerfCounter("jdk.module.bootstrap.optionsAndRootsTime"); 683 static PerfCounter resolveTime 684 = PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime"); 685 static PerfCounter layerCreateTime 686 = PerfCounter.newPerfCounter("jdk.module.bootstrap.layerCreateTime"); 687 static PerfCounter loadModulesTime 688 = PerfCounter.newPerfCounter("jdk.module.bootstrap.loadModulesTime"); 689 static PerfCounter bootstrapTime 690 = PerfCounter.newPerfCounter("jdk.module.bootstrap.totalTime"); 691 } 692 } | 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); 299 if (cl == null) { 300 301 if (upgradeModulePath != null 302 && upgradeModulePath.find(name).isPresent()) 303 fail(name + ": cannot be loaded from upgrade module path"); 304 305 if (!systemModules.find(name).isPresent()) 306 fail(name + ": cannot be loaded from application module path"); 307 } 308 } 309 310 // check if module specified in --patch-module is present 311 for (String mn: patcher.patchedModules()) { 312 if (!cf.findModule(mn).isPresent()) { 313 warnUnknownModule(PATCH_MODULE, mn); 314 } 315 } 316 } 317 318 319 long t4 = System.nanoTime(); 320 321 // define modules to VM/runtime 322 Layer bootLayer = Layer.empty().defineModules(cf, clf); 323 324 PerfCounters.layerCreateTime.addElapsedTimeFrom(t4); 325 326 327 long t5 = System.nanoTime(); 328 329 // define the module to its class loader, except java.base 330 for (ResolvedModule resolvedModule : cf.modules()) { 331 ModuleReference mref = resolvedModule.reference(); 332 String name = mref.descriptor().name(); 333 ClassLoader cl = clf.apply(name); 334 if (cl == null) { 335 if (!name.equals(JAVA_BASE)) BootLoader.loadModule(mref); 454 return modules; 455 } 456 457 /** 458 * Process the --add-reads options to add any additional read edges that 459 * are specified on the command-line. 460 */ 461 private static void addExtraReads(Layer bootLayer) { 462 463 // decode the command line options 464 Map<String, List<String>> map = decode("jdk.module.addreads."); 465 if (map.isEmpty()) 466 return; 467 468 for (Map.Entry<String, List<String>> e : map.entrySet()) { 469 470 // the key is $MODULE 471 String mn = e.getKey(); 472 Optional<Module> om = bootLayer.findModule(mn); 473 if (!om.isPresent()) { 474 warnUnknownModule(ADD_READS, mn); 475 continue; 476 } 477 Module m = om.get(); 478 479 // the value is the set of other modules (by name) 480 for (String name : e.getValue()) { 481 if (ALL_UNNAMED.equals(name)) { 482 Modules.addReadsAllUnnamed(m); 483 } else { 484 om = bootLayer.findModule(name); 485 if (om.isPresent()) { 486 Modules.addReads(m, om.get()); 487 } else { 488 warnUnknownModule(ADD_READS, name); 489 } 490 } 491 } 492 } 493 } 494 495 /** 496 * Process the --add-exports and --add-opens options to export/open 497 * additional packages specified on the command-line. 498 */ 499 private static void addExtraExportsAndOpens(Layer bootLayer) { 500 501 // --add-exports 502 String prefix = "jdk.module.addexports."; 503 Map<String, List<String>> extraExports = decode(prefix); 504 if (!extraExports.isEmpty()) { 505 addExtraExportsOrOpens(bootLayer, extraExports, false); 506 } 507 508 // --add-opens 509 prefix = "jdk.module.addopens."; 510 Map<String, List<String>> extraOpens = decode(prefix); 511 if (!extraOpens.isEmpty()) { 512 addExtraExportsOrOpens(bootLayer, extraOpens, true); 513 } 514 } 515 516 private static void addExtraExportsOrOpens(Layer bootLayer, 517 Map<String, List<String>> map, 518 boolean opens) 519 { 520 String option = opens ? ADD_OPENS : ADD_EXPORTS; 521 for (Map.Entry<String, List<String>> e : map.entrySet()) { 522 523 // the key is $MODULE/$PACKAGE 524 String key = e.getKey(); 525 String[] s = key.split("/"); 526 if (s.length != 2) 527 fail(unableToParse(option, "<module>/<package>", key)); 528 529 String mn = s[0]; 530 String pn = s[1]; 531 if (mn.isEmpty() || pn.isEmpty()) 532 fail(unableToParse(option, "<module>/<package>", key)); 533 534 // The exporting module is in the boot layer 535 Module m; 536 Optional<Module> om = bootLayer.findModule(mn); 537 if (!om.isPresent()) { 538 warnUnknownModule(option, mn); 539 continue; 540 } 541 542 m = om.get(); 543 544 if (!m.getDescriptor().packages().contains(pn)) { 545 warn("package " + pn + " not in " + mn); 546 continue; 547 } 548 549 // the value is the set of modules to export to (by name) 550 for (String name : e.getValue()) { 551 boolean allUnnamed = false; 552 Module other = null; 553 if (ALL_UNNAMED.equals(name)) { 554 allUnnamed = true; 555 } else { 556 om = bootLayer.findModule(name); 557 if (om.isPresent()) { 558 other = om.get(); 559 } else { 560 warnUnknownModule(option, name); 561 continue; 562 } 563 } 564 if (allUnnamed) { 565 if (opens) { 566 Modules.addOpensToAllUnnamed(m, pn); 567 } else { 568 Modules.addExportsToAllUnnamed(m, pn); 569 } 570 } else { 571 if (opens) { 572 Modules.addOpens(m, pn, other); 573 } else { 574 Modules.addExports(m, pn, other); 575 } 576 } 577 578 } 579 } 580 } 584 * --patch-modules options that are encoded in system properties. 585 * 586 * @param prefix the system property prefix 587 * @praam regex the regex for splitting the RHS of the option value 588 */ 589 private static Map<String, List<String>> decode(String prefix, 590 String regex, 591 boolean allowDuplicates) { 592 int index = 0; 593 // the system property is removed after decoding 594 String value = getAndRemoveProperty(prefix + index); 595 if (value == null) 596 return Collections.emptyMap(); 597 598 Map<String, List<String>> map = new HashMap<>(); 599 600 while (value != null) { 601 602 int pos = value.indexOf('='); 603 if (pos == -1) 604 fail(unableToParse(option(prefix), "<module>=<value>", value)); 605 if (pos == 0) 606 fail(unableToParse(option(prefix), "<module>=<value>", value)); 607 608 // key is <module> or <module>/<package> 609 String key = value.substring(0, pos); 610 611 String rhs = value.substring(pos+1); 612 if (rhs.isEmpty()) 613 fail(unableToParse(option(prefix), "<module>=<value>", value)); 614 615 // value is <module>(,<module>)* or <file>(<pathsep><file>)* 616 if (!allowDuplicates && map.containsKey(key)) 617 fail(key + " specified more than once in " + option(prefix)); 618 List<String> values = map.computeIfAbsent(key, k -> new ArrayList<>()); 619 int ntargets = 0; 620 for (String s : rhs.split(regex)) { 621 if (s.length() > 0) { 622 values.add(s); 623 ntargets++; 624 } 625 } 626 if (ntargets == 0) 627 fail("Target must be specified: " + option(prefix) + " " + value); 628 629 index++; 630 value = getAndRemoveProperty(prefix + index); 631 } 632 633 return map; 634 } 635 636 /** 637 * Decodes the values of --add-reads, -add-exports or --add-opens 638 * which use the "," to separate the RHS of the option value. 639 */ 640 private static Map<String, List<String>> decode(String prefix) { 641 return decode(prefix, ",", true); 642 } 643 644 /** 645 * Gets and remove the named system property 646 */ 647 private static String getAndRemoveProperty(String key) { 669 } else { 670 incubating += ", " + mn; 671 } 672 } 673 } 674 if (incubating != null) 675 warn("Using incubator modules: " + incubating); 676 } 677 678 /** 679 * Throws a RuntimeException with the given message 680 */ 681 static void fail(String m) { 682 throw new RuntimeException(m); 683 } 684 685 static void warn(String m) { 686 System.err.println("WARNING: " + m); 687 } 688 689 static void warnUnknownModule(String option, String mn) { 690 warn("Unknown module: " + mn + " specified in " + option); 691 } 692 693 static String unableToParse(String option, String text, String value) { 694 return "Unable to parse " + option + " " + text + ": " + value; 695 } 696 697 private static final String ADD_MODULES = "--add-modules"; 698 private static final String ADD_EXPORTS = "--add-exports"; 699 private static final String ADD_OPENS = "--add-opens"; 700 private static final String ADD_READS = "--add-reads"; 701 private static final String PATCH_MODULE = "--patch-module"; 702 703 704 /* 705 * Returns the command-line option name corresponds to the specified 706 * system property prefix. 707 */ 708 static String option(String prefix) { 709 switch (prefix) { 710 case "jdk.module.addexports.": 711 return ADD_EXPORTS; 712 case "jdk.module.addopens.": 713 return ADD_OPENS; 714 case "jdk.module.addreads.": 715 return ADD_READS; 716 case "jdk.module.patch.": 717 return PATCH_MODULE; 718 case "jdk.module.addmods.": 719 return ADD_MODULES; 720 default: 721 throw new IllegalArgumentException(prefix); 722 } 723 } 724 725 static class PerfCounters { 726 727 static PerfCounter systemModulesTime 728 = PerfCounter.newPerfCounter("jdk.module.bootstrap.systemModulesTime"); 729 static PerfCounter defineBaseTime 730 = PerfCounter.newPerfCounter("jdk.module.bootstrap.defineBaseTime"); 731 static PerfCounter optionsAndRootsTime 732 = PerfCounter.newPerfCounter("jdk.module.bootstrap.optionsAndRootsTime"); 733 static PerfCounter resolveTime 734 = PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime"); 735 static PerfCounter layerCreateTime 736 = PerfCounter.newPerfCounter("jdk.module.bootstrap.layerCreateTime"); 737 static PerfCounter loadModulesTime 738 = PerfCounter.newPerfCounter("jdk.module.bootstrap.loadModulesTime"); 739 static PerfCounter bootstrapTime 740 = PerfCounter.newPerfCounter("jdk.module.bootstrap.totalTime"); 741 } 742 } |