783 break;
784 case "debug":
785 mode = IllegalAccessLogger.Mode.DEBUG;
786 break;
787 default:
788 fail("Value specified to --illegal-access not recognized:"
789 + " '" + value + "'");
790 return;
791 }
792 }
793 IllegalAccessLogger.Builder builder
794 = new IllegalAccessLogger.Builder(mode, System.err);
795
796 if (concealedPackagesToOpen.isEmpty() && exportedPackagesToOpen.isEmpty()) {
797 // need to generate (exploded build)
798 IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
799 concealedPackagesToOpen = maps.concealedPackagesToOpen();
800 exportedPackagesToOpen = maps.exportedPackagesToOpen();
801 }
802
803 // open specific packages in the system modules
804 for (Module m : bootLayer.modules()) {
805 ModuleDescriptor descriptor = m.getDescriptor();
806 String name = m.getName();
807
808 // skip open modules
809 if (descriptor.isOpen()) {
810 continue;
811 }
812
813 // skip modules loaded from the upgrade module path
814 if (upgradeModulePath != null
815 && upgradeModulePath.find(name).isPresent()) {
816 continue;
817 }
818
819 Set<String> concealedPackages = concealedPackagesToOpen.getOrDefault(name, Set.of());
820 Set<String> exportedPackages = exportedPackagesToOpen.getOrDefault(name, Set.of());
821
822 // refresh the set of concealed and exported packages if needed
823 if (extraExportsOrOpens) {
824 concealedPackages = new HashSet<>(concealedPackages);
825 exportedPackages = new HashSet<>(exportedPackages);
826 Iterator<String> iterator = concealedPackages.iterator();
827 while (iterator.hasNext()) {
828 String pn = iterator.next();
829 if (m.isExported(pn, BootLoader.getUnnamedModule())) {
830 // concealed package is exported to ALL-UNNAMED
831 iterator.remove();
832 exportedPackages.add(pn);
833 }
834 }
835 iterator = exportedPackages.iterator();
836 while (iterator.hasNext()) {
837 String pn = iterator.next();
838 if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
839 // exported package is opened to ALL-UNNAMED
840 iterator.remove();
841 }
842 }
843 }
844
845 // log reflective access to all types in concealed packages
846 builder.logAccessToConcealedPackages(m, concealedPackages);
847
848 // log reflective access to non-public members/types in exported packages
849 builder.logAccessToExportedPackages(m, exportedPackages);
850
851 // open the packages to unnamed modules
852 JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
853 jla.addOpensToAllUnnamed(m, concat(concealedPackages.iterator(),
854 exportedPackages.iterator()));
855 }
856
857 builder.complete();
858 }
859
860 /**
861 * Decodes the values of --add-reads, -add-exports, --add-opens or
862 * --patch-modules options that are encoded in system properties.
863 *
864 * @param prefix the system property prefix
865 * @praam regex the regex for splitting the RHS of the option value
866 */
867 private static Map<String, List<String>> decode(String prefix,
868 String regex,
869 boolean allowDuplicates) {
870 int index = 0;
871 // the system property is removed after decoding
872 String value = getAndRemoveProperty(prefix + index);
873 if (value == null)
874 return Map.of();
976
977 /*
978 * Returns the command-line option name corresponds to the specified
979 * system property prefix.
980 */
981 static String option(String prefix) {
982 switch (prefix) {
983 case "jdk.module.addexports.":
984 return ADD_EXPORTS;
985 case "jdk.module.addopens.":
986 return ADD_OPENS;
987 case "jdk.module.addreads.":
988 return ADD_READS;
989 case "jdk.module.patch.":
990 return PATCH_MODULE;
991 case "jdk.module.addmods.":
992 return ADD_MODULES;
993 default:
994 throw new IllegalArgumentException(prefix);
995 }
996 }
997
998 /**
999 * Returns an iterator that yields all elements of the first iterator
1000 * followed by all the elements of the second iterator.
1001 */
1002 static <T> Iterator<T> concat(Iterator<T> iterator1, Iterator<T> iterator2) {
1003 return new Iterator<T>() {
1004 @Override
1005 public boolean hasNext() {
1006 return iterator1.hasNext() || iterator2.hasNext();
1007 }
1008 @Override
1009 public T next() {
1010 if (iterator1.hasNext()) return iterator1.next();
1011 if (iterator2.hasNext()) return iterator2.next();
1012 throw new NoSuchElementException();
1013 }
1014 };
1015 }
1016
1017 /**
1018 * Wraps a (potentially not thread safe) ModuleFinder created during startup
1019 * for use after startup.
1020 */
1021 static class SafeModuleFinder implements ModuleFinder {
1022 private final Set<ModuleReference> mrefs;
1023 private volatile Map<String, ModuleReference> nameToModule;
1024
1025 SafeModuleFinder(ModuleFinder finder) {
1026 this.mrefs = Collections.unmodifiableSet(finder.findAll());
1027 }
1028 @Override
1029 public Optional<ModuleReference> find(String name) {
1030 Objects.requireNonNull(name);
1031 Map<String, ModuleReference> nameToModule = this.nameToModule;
1032 if (nameToModule == null) {
1033 this.nameToModule = nameToModule = mrefs.stream()
1034 .collect(Collectors.toMap(m -> m.descriptor().name(),
|
783 break;
784 case "debug":
785 mode = IllegalAccessLogger.Mode.DEBUG;
786 break;
787 default:
788 fail("Value specified to --illegal-access not recognized:"
789 + " '" + value + "'");
790 return;
791 }
792 }
793 IllegalAccessLogger.Builder builder
794 = new IllegalAccessLogger.Builder(mode, System.err);
795
796 if (concealedPackagesToOpen.isEmpty() && exportedPackagesToOpen.isEmpty()) {
797 // need to generate (exploded build)
798 IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
799 concealedPackagesToOpen = maps.concealedPackagesToOpen();
800 exportedPackagesToOpen = maps.exportedPackagesToOpen();
801 }
802
803 Set<String> emptySet = Set.of();
804
805 // open specific packages in the system modules
806 for (Module m : bootLayer.modules()) {
807 ModuleDescriptor descriptor = m.getDescriptor();
808 String name = m.getName();
809
810 // skip open modules
811 if (descriptor.isOpen()) {
812 continue;
813 }
814
815 // skip modules loaded from the upgrade module path
816 if (upgradeModulePath != null
817 && upgradeModulePath.find(name).isPresent()) {
818 continue;
819 }
820
821 Set<String> concealedPackages = concealedPackagesToOpen.getOrDefault(name, emptySet);
822 Set<String> exportedPackages = exportedPackagesToOpen.getOrDefault(name, emptySet);
823
824 // refresh the set of concealed and exported packages if needed
825 if (extraExportsOrOpens) {
826 concealedPackages = new HashSet<>(concealedPackages);
827 exportedPackages = new HashSet<>(exportedPackages);
828 Iterator<String> iterator = concealedPackages.iterator();
829 while (iterator.hasNext()) {
830 String pn = iterator.next();
831 if (m.isExported(pn, BootLoader.getUnnamedModule())) {
832 // concealed package is exported to ALL-UNNAMED
833 iterator.remove();
834 exportedPackages.add(pn);
835 }
836 }
837 iterator = exportedPackages.iterator();
838 while (iterator.hasNext()) {
839 String pn = iterator.next();
840 if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
841 // exported package is opened to ALL-UNNAMED
842 iterator.remove();
843 }
844 }
845 }
846
847 // log reflective access to all types in concealed packages
848 builder.logAccessToConcealedPackages(m, concealedPackages);
849
850 // log reflective access to non-public members/types in exported packages
851 builder.logAccessToExportedPackages(m, exportedPackages);
852
853 // open the packages to unnamed modules
854 JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
855 jla.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
856 }
857
858 builder.complete();
859 }
860
861 /**
862 * Decodes the values of --add-reads, -add-exports, --add-opens or
863 * --patch-modules options that are encoded in system properties.
864 *
865 * @param prefix the system property prefix
866 * @praam regex the regex for splitting the RHS of the option value
867 */
868 private static Map<String, List<String>> decode(String prefix,
869 String regex,
870 boolean allowDuplicates) {
871 int index = 0;
872 // the system property is removed after decoding
873 String value = getAndRemoveProperty(prefix + index);
874 if (value == null)
875 return Map.of();
977
978 /*
979 * Returns the command-line option name corresponds to the specified
980 * system property prefix.
981 */
982 static String option(String prefix) {
983 switch (prefix) {
984 case "jdk.module.addexports.":
985 return ADD_EXPORTS;
986 case "jdk.module.addopens.":
987 return ADD_OPENS;
988 case "jdk.module.addreads.":
989 return ADD_READS;
990 case "jdk.module.patch.":
991 return PATCH_MODULE;
992 case "jdk.module.addmods.":
993 return ADD_MODULES;
994 default:
995 throw new IllegalArgumentException(prefix);
996 }
997 }
998
999 /**
1000 * Wraps a (potentially not thread safe) ModuleFinder created during startup
1001 * for use after startup.
1002 */
1003 static class SafeModuleFinder implements ModuleFinder {
1004 private final Set<ModuleReference> mrefs;
1005 private volatile Map<String, ModuleReference> nameToModule;
1006
1007 SafeModuleFinder(ModuleFinder finder) {
1008 this.mrefs = Collections.unmodifiableSet(finder.findAll());
1009 }
1010 @Override
1011 public Optional<ModuleReference> find(String name) {
1012 Objects.requireNonNull(name);
1013 Map<String, ModuleReference> nameToModule = this.nameToModule;
1014 if (nameToModule == null) {
1015 this.nameToModule = nameToModule = mrefs.stream()
1016 .collect(Collectors.toMap(m -> m.descriptor().name(),
|