37 import java.lang.module.ResolvedModule; |
37 import java.lang.module.ResolvedModule; |
38 import java.net.URI; |
38 import java.net.URI; |
39 import java.net.URL; |
39 import java.net.URL; |
40 import java.security.AccessController; |
40 import java.security.AccessController; |
41 import java.security.PrivilegedAction; |
41 import java.security.PrivilegedAction; |
|
42 import java.util.Collections; |
42 import java.util.HashMap; |
43 import java.util.HashMap; |
43 import java.util.HashSet; |
44 import java.util.HashSet; |
|
45 import java.util.List; |
44 import java.util.Map; |
46 import java.util.Map; |
45 import java.util.Objects; |
47 import java.util.Objects; |
46 import java.util.Optional; |
48 import java.util.Optional; |
47 import java.util.Set; |
49 import java.util.Set; |
48 import java.util.concurrent.ConcurrentHashMap; |
50 import java.util.concurrent.ConcurrentHashMap; |
49 import java.util.function.Function; |
51 import java.util.function.Function; |
50 import java.util.stream.Stream; |
52 import java.util.stream.Stream; |
51 |
53 |
52 import jdk.internal.loader.BuiltinClassLoader; |
54 import jdk.internal.loader.BuiltinClassLoader; |
53 import jdk.internal.loader.BootLoader; |
55 import jdk.internal.loader.BootLoader; |
54 import jdk.internal.loader.ResourceHelper; |
|
55 import jdk.internal.misc.JavaLangAccess; |
56 import jdk.internal.misc.JavaLangAccess; |
56 import jdk.internal.misc.JavaLangReflectModuleAccess; |
57 import jdk.internal.misc.JavaLangReflectModuleAccess; |
57 import jdk.internal.misc.SharedSecrets; |
58 import jdk.internal.misc.SharedSecrets; |
58 import jdk.internal.module.ServicesCatalog; |
59 import jdk.internal.module.ServicesCatalog; |
|
60 import jdk.internal.module.Resources; |
59 import jdk.internal.org.objectweb.asm.AnnotationVisitor; |
61 import jdk.internal.org.objectweb.asm.AnnotationVisitor; |
60 import jdk.internal.org.objectweb.asm.Attribute; |
62 import jdk.internal.org.objectweb.asm.Attribute; |
61 import jdk.internal.org.objectweb.asm.ClassReader; |
63 import jdk.internal.org.objectweb.asm.ClassReader; |
62 import jdk.internal.org.objectweb.asm.ClassVisitor; |
64 import jdk.internal.org.objectweb.asm.ClassVisitor; |
63 import jdk.internal.org.objectweb.asm.ClassWriter; |
65 import jdk.internal.org.objectweb.asm.ClassWriter; |
367 * Makes the given {@code Module} readable to this module. |
369 * Makes the given {@code Module} readable to this module. |
368 * |
370 * |
369 * If {@code syncVM} is {@code true} then the VM is notified. |
371 * If {@code syncVM} is {@code true} then the VM is notified. |
370 */ |
372 */ |
371 private void implAddReads(Module other, boolean syncVM) { |
373 private void implAddReads(Module other, boolean syncVM) { |
372 Objects.requireNonNull(other); |
374 if (!canRead(other)) { |
373 |
375 // update VM first, just in case it fails |
374 // nothing to do |
376 if (syncVM) { |
375 if (other == this || !this.isNamed()) |
377 if (other == ALL_UNNAMED_MODULE) { |
376 return; |
378 addReads0(this, null); |
377 |
379 } else { |
378 // check if we already read this module |
380 addReads0(this, other); |
379 Set<Module> reads = this.reads; |
381 } |
380 if (reads != null && reads.contains(other)) |
382 } |
381 return; |
383 |
382 |
384 // add reflective read |
383 // update VM first, just in case it fails |
385 reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE); |
384 if (syncVM) { |
386 } |
385 if (other == ALL_UNNAMED_MODULE) { |
|
386 addReads0(this, null); |
|
387 } else { |
|
388 addReads0(this, other); |
|
389 } |
|
390 } |
|
391 |
|
392 // add reflective read |
|
393 reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE); |
|
394 } |
387 } |
395 |
388 |
396 |
389 |
397 // -- exported and open packages -- |
390 // -- exported and open packages -- |
398 |
391 |
551 |
544 |
552 /** |
545 /** |
553 * Returns {@code true} if this module exports or opens a package to |
546 * Returns {@code true} if this module exports or opens a package to |
554 * the given module via its module declaration. |
547 * the given module via its module declaration. |
555 */ |
548 */ |
556 boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) { |
549 private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) { |
557 // package is open to everyone or <other> |
550 // package is open to everyone or <other> |
558 Map<String, Set<Module>> openPackages = this.openPackages; |
551 Map<String, Set<Module>> openPackages = this.openPackages; |
559 if (openPackages != null) { |
552 if (openPackages != null) { |
560 Set<Module> targets = openPackages.get(pn); |
553 Set<Module> targets = openPackages.get(pn); |
561 if (targets != null) { |
554 if (targets != null) { |
907 |
900 |
908 /** |
901 /** |
909 * Returns an array of the package names of the packages in this module. |
902 * Returns an array of the package names of the packages in this module. |
910 * |
903 * |
911 * <p> For named modules, the returned array contains an element for each |
904 * <p> For named modules, the returned array contains an element for each |
912 * package in the module. It may contain elements corresponding to packages |
905 * package in the module. </p> |
913 * added to the module, <a href="Proxy.html#dynamicmodule">dynamic modules</a> |
|
914 * for example, after it was loaded. |
|
915 * |
906 * |
916 * <p> For unnamed modules, this method is the equivalent to invoking the |
907 * <p> For unnamed modules, this method is the equivalent to invoking the |
917 * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of |
908 * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of |
918 * this module's class loader and returning the array of package names. </p> |
909 * this module's class loader and returning the array of package names. </p> |
919 * |
910 * |
1078 Module m = nameToModule.get(mn); |
1060 Module m = nameToModule.get(mn); |
1079 assert m != null; |
1061 assert m != null; |
1080 |
1062 |
1081 // reads |
1063 // reads |
1082 Set<Module> reads = new HashSet<>(); |
1064 Set<Module> reads = new HashSet<>(); |
|
1065 |
|
1066 // name -> source Module when in parent layer |
|
1067 Map<String, Module> nameToSource = Collections.emptyMap(); |
|
1068 |
1083 for (ResolvedModule other : resolvedModule.reads()) { |
1069 for (ResolvedModule other : resolvedModule.reads()) { |
1084 Module m2 = null; |
1070 Module m2 = null; |
1085 if (other.configuration() == cf) { |
1071 if (other.configuration() == cf) { |
1086 String dn = other.reference().descriptor().name(); |
1072 // this configuration |
1087 m2 = nameToModule.get(dn); |
1073 m2 = nameToModule.get(other.name()); |
|
1074 assert m2 != null; |
1088 } else { |
1075 } else { |
|
1076 // parent layer |
1089 for (Layer parent: layer.parents()) { |
1077 for (Layer parent: layer.parents()) { |
1090 m2 = findModule(parent, other); |
1078 m2 = findModule(parent, other); |
1091 if (m2 != null) |
1079 if (m2 != null) |
1092 break; |
1080 break; |
1093 } |
1081 } |
1094 } |
1082 assert m2 != null; |
1095 assert m2 != null; |
1083 if (nameToSource.isEmpty()) |
1096 |
1084 nameToSource = new HashMap<>(); |
|
1085 nameToSource.put(other.name(), m2); |
|
1086 } |
1097 reads.add(m2); |
1087 reads.add(m2); |
1098 |
1088 |
1099 // update VM view |
1089 // update VM view |
1100 addReads0(m, m2); |
1090 addReads0(m, m2); |
1101 } |
1091 } |
1105 if (descriptor.isAutomatic()) { |
1095 if (descriptor.isAutomatic()) { |
1106 m.implAddReads(ALL_UNNAMED_MODULE, true); |
1096 m.implAddReads(ALL_UNNAMED_MODULE, true); |
1107 } |
1097 } |
1108 |
1098 |
1109 // exports and opens |
1099 // exports and opens |
1110 initExportsAndOpens(descriptor, nameToModule, m); |
1100 initExportsAndOpens(m, nameToSource, nameToModule, layer.parents()); |
1111 } |
1101 } |
1112 |
1102 |
1113 // register the modules in the boot layer |
1103 // register the modules in the boot layer |
1114 if (isBootLayer) { |
1104 if (isBootLayer) { |
1115 for (ResolvedModule resolvedModule : cf.modules()) { |
1105 for (ResolvedModule resolvedModule : cf.modules()) { |
1157 return m; |
1147 return m; |
1158 }) |
1148 }) |
1159 .orElse(null); |
1149 .orElse(null); |
1160 } |
1150 } |
1161 |
1151 |
|
1152 |
1162 /** |
1153 /** |
1163 * Initialize the maps of exported and open packages for module m. |
1154 * Initialize the maps of exported and open packages for module m. |
1164 */ |
1155 */ |
1165 private static void initExportsAndOpens(ModuleDescriptor descriptor, |
1156 private static void initExportsAndOpens(Module m, |
|
1157 Map<String, Module> nameToSource, |
1166 Map<String, Module> nameToModule, |
1158 Map<String, Module> nameToModule, |
1167 Module m) |
1159 List<Layer> parents) { |
1168 { |
|
1169 // The VM doesn't special case open or automatic modules so need to |
1160 // The VM doesn't special case open or automatic modules so need to |
1170 // export all packages |
1161 // export all packages |
|
1162 ModuleDescriptor descriptor = m.getDescriptor(); |
1171 if (descriptor.isOpen() || descriptor.isAutomatic()) { |
1163 if (descriptor.isOpen() || descriptor.isAutomatic()) { |
1172 assert descriptor.opens().isEmpty(); |
1164 assert descriptor.opens().isEmpty(); |
1173 for (String source : descriptor.packages()) { |
1165 for (String source : descriptor.packages()) { |
1174 addExportsToAll0(m, source); |
1166 addExportsToAll0(m, source); |
1175 } |
1167 } |
1185 |
1177 |
1186 if (opens.isQualified()) { |
1178 if (opens.isQualified()) { |
1187 // qualified opens |
1179 // qualified opens |
1188 Set<Module> targets = new HashSet<>(); |
1180 Set<Module> targets = new HashSet<>(); |
1189 for (String target : opens.targets()) { |
1181 for (String target : opens.targets()) { |
1190 // only open to modules that are in this configuration |
1182 Module m2 = findModule(target, nameToSource, nameToModule, parents); |
1191 Module m2 = nameToModule.get(target); |
|
1192 if (m2 != null) { |
1183 if (m2 != null) { |
1193 addExports0(m, source, m2); |
1184 addExports0(m, source, m2); |
1194 targets.add(m2); |
1185 targets.add(m2); |
1195 } |
1186 } |
1196 } |
1187 } |
1215 |
1206 |
1216 if (exports.isQualified()) { |
1207 if (exports.isQualified()) { |
1217 // qualified exports |
1208 // qualified exports |
1218 Set<Module> targets = new HashSet<>(); |
1209 Set<Module> targets = new HashSet<>(); |
1219 for (String target : exports.targets()) { |
1210 for (String target : exports.targets()) { |
1220 // only export to modules that are in this configuration |
1211 Module m2 = findModule(target, nameToSource, nameToModule, parents); |
1221 Module m2 = nameToModule.get(target); |
|
1222 if (m2 != null) { |
1212 if (m2 != null) { |
1223 // skip qualified export if already open to m2 |
1213 // skip qualified export if already open to m2 |
1224 if (openToTargets == null || !openToTargets.contains(m2)) { |
1214 if (openToTargets == null || !openToTargets.contains(m2)) { |
1225 addExports0(m, source, m2); |
1215 addExports0(m, source, m2); |
1226 targets.add(m2); |
1216 targets.add(m2); |
1240 |
1230 |
1241 if (!openPackages.isEmpty()) |
1231 if (!openPackages.isEmpty()) |
1242 m.openPackages = openPackages; |
1232 m.openPackages = openPackages; |
1243 if (!exportedPackages.isEmpty()) |
1233 if (!exportedPackages.isEmpty()) |
1244 m.exportedPackages = exportedPackages; |
1234 m.exportedPackages = exportedPackages; |
|
1235 } |
|
1236 |
|
1237 /** |
|
1238 * Find the runtime Module with the given name. The module name is the |
|
1239 * name of a target module in a qualified exports or opens directive. |
|
1240 * |
|
1241 * @param target The target module to find |
|
1242 * @param nameToSource The modules in parent layers that are read |
|
1243 * @param nameToModule The modules in the layer under construction |
|
1244 * @param parents The parent layers |
|
1245 */ |
|
1246 private static Module findModule(String target, |
|
1247 Map<String, Module> nameToSource, |
|
1248 Map<String, Module> nameToModule, |
|
1249 List<Layer> parents) { |
|
1250 Module m = nameToSource.get(target); |
|
1251 if (m == null) { |
|
1252 m = nameToModule.get(target); |
|
1253 if (m == null) { |
|
1254 for (Layer parent : parents) { |
|
1255 m = parent.findModule(target).orElse(null); |
|
1256 if (m != null) break; |
|
1257 } |
|
1258 } |
|
1259 } |
|
1260 return m; |
1245 } |
1261 } |
1246 |
1262 |
1247 |
1263 |
1248 // -- annotations -- |
1264 // -- annotations -- |
1249 |
1265 |
1426 public InputStream getResourceAsStream(String name) throws IOException { |
1442 public InputStream getResourceAsStream(String name) throws IOException { |
1427 if (name.startsWith("/")) { |
1443 if (name.startsWith("/")) { |
1428 name = name.substring(1); |
1444 name = name.substring(1); |
1429 } |
1445 } |
1430 |
1446 |
1431 if (isNamed() && !ResourceHelper.isSimpleResource(name)) { |
1447 if (isNamed() && Resources.canEncapsulate(name)) { |
1432 Module caller = Reflection.getCallerClass().getModule(); |
1448 Module caller = Reflection.getCallerClass().getModule(); |
1433 if (caller != this && caller != Object.class.getModule()) { |
1449 if (caller != this && caller != Object.class.getModule()) { |
1434 // ignore packages added for proxies via addPackage |
1450 // ignore packages added for proxies via addPackage |
1435 Set<String> packages = getDescriptor().packages(); |
1451 Set<String> packages = getDescriptor().packages(); |
1436 String pn = ResourceHelper.getPackageName(name); |
1452 String pn = Resources.toPackageName(name); |
1437 if (packages.contains(pn) && !isOpen(pn, caller)) { |
1453 if (packages.contains(pn) && !isOpen(pn, caller)) { |
1438 // resource is in package not open to caller |
1454 // resource is in package not open to caller |
1439 return null; |
1455 return null; |
1440 } |
1456 } |
1441 } |
1457 } |
1529 @Override |
1545 @Override |
1530 public void addReadsAllUnnamed(Module m) { |
1546 public void addReadsAllUnnamed(Module m) { |
1531 m.implAddReads(Module.ALL_UNNAMED_MODULE); |
1547 m.implAddReads(Module.ALL_UNNAMED_MODULE); |
1532 } |
1548 } |
1533 @Override |
1549 @Override |
|
1550 public void addExports(Module m, String pn) { |
|
1551 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true); |
|
1552 } |
|
1553 @Override |
1534 public void addExports(Module m, String pn, Module other) { |
1554 public void addExports(Module m, String pn, Module other) { |
1535 m.implAddExportsOrOpens(pn, other, false, true); |
1555 m.implAddExportsOrOpens(pn, other, false, true); |
|
1556 } |
|
1557 @Override |
|
1558 public void addExportsToAllUnnamed(Module m, String pn) { |
|
1559 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true); |
|
1560 } |
|
1561 @Override |
|
1562 public void addOpens(Module m, String pn) { |
|
1563 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true); |
1536 } |
1564 } |
1537 @Override |
1565 @Override |
1538 public void addOpens(Module m, String pn, Module other) { |
1566 public void addOpens(Module m, String pn, Module other) { |
1539 m.implAddExportsOrOpens(pn, other, true, true); |
1567 m.implAddExportsOrOpens(pn, other, true, true); |
1540 } |
1568 } |
1541 @Override |
1569 @Override |
1542 public void addExportsToAll(Module m, String pn) { |
|
1543 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true); |
|
1544 } |
|
1545 @Override |
|
1546 public void addOpensToAll(Module m, String pn) { |
|
1547 m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true); |
|
1548 } |
|
1549 @Override |
|
1550 public void addExportsToAllUnnamed(Module m, String pn) { |
|
1551 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true); |
|
1552 } |
|
1553 @Override |
|
1554 public void addOpensToAllUnnamed(Module m, String pn) { |
1570 public void addOpensToAllUnnamed(Module m, String pn) { |
1555 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true); |
1571 m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true); |
1556 } |
1572 } |
1557 @Override |
1573 @Override |
1558 public void addUses(Module m, Class<?> service) { |
1574 public void addUses(Module m, Class<?> service) { |
1559 m.implAddUses(service); |
1575 m.implAddUses(service); |
1560 } |
1576 } |
1561 @Override |
1577 @Override |
1562 public void addPackage(Module m, String pn) { |
|
1563 m.implAddPackage(pn, true); |
|
1564 } |
|
1565 @Override |
|
1566 public ServicesCatalog getServicesCatalog(Layer layer) { |
1578 public ServicesCatalog getServicesCatalog(Layer layer) { |
1567 return layer.getServicesCatalog(); |
1579 return layer.getServicesCatalog(); |
1568 } |
1580 } |
1569 @Override |
1581 @Override |
1570 public Stream<Layer> layers(Layer layer) { |
1582 public Stream<Layer> layers(Layer layer) { |