< prev index next >

src/java.base/share/classes/java/lang/reflect/Module.java

Print this page




  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.reflect;
  27 
  28 import java.io.IOException;
  29 import java.io.InputStream;
  30 import java.lang.annotation.Annotation;
  31 import java.lang.module.Configuration;
  32 import java.lang.module.ModuleReference;
  33 import java.lang.module.ModuleDescriptor;
  34 import java.lang.module.ModuleDescriptor.Exports;
  35 import java.lang.module.ModuleDescriptor.Opens;
  36 import java.lang.module.ModuleDescriptor.Version;
  37 import java.lang.module.ResolvedModule;
  38 import java.net.URI;
  39 import java.net.URL;
  40 import java.security.AccessController;
  41 import java.security.PrivilegedAction;

  42 import java.util.HashMap;
  43 import java.util.HashSet;

  44 import java.util.Map;
  45 import java.util.Objects;
  46 import java.util.Optional;
  47 import java.util.Set;
  48 import java.util.concurrent.ConcurrentHashMap;
  49 import java.util.function.Function;
  50 import java.util.stream.Stream;
  51 
  52 import jdk.internal.loader.BuiltinClassLoader;
  53 import jdk.internal.loader.BootLoader;
  54 import jdk.internal.loader.ResourceHelper;
  55 import jdk.internal.misc.JavaLangAccess;
  56 import jdk.internal.misc.JavaLangReflectModuleAccess;
  57 import jdk.internal.misc.SharedSecrets;
  58 import jdk.internal.module.ServicesCatalog;

  59 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
  60 import jdk.internal.org.objectweb.asm.Attribute;
  61 import jdk.internal.org.objectweb.asm.ClassReader;
  62 import jdk.internal.org.objectweb.asm.ClassVisitor;
  63 import jdk.internal.org.objectweb.asm.ClassWriter;
  64 import jdk.internal.org.objectweb.asm.Opcodes;
  65 import jdk.internal.reflect.CallerSensitive;
  66 import jdk.internal.reflect.Reflection;
  67 import sun.security.util.SecurityConstants;
  68 
  69 /**
  70  * Represents a run-time module, either {@link #isNamed() named} or unnamed.
  71  *
  72  * <p> Named modules have a {@link #getName() name} and are constructed by the
  73  * Java Virtual Machine when a graph of modules is defined to the Java virtual
  74  * machine to create a module {@link Layer Layer}. </p>
  75  *
  76  * <p> An unnamed module does not have a name. There is an unnamed module for
  77  * each {@link ClassLoader ClassLoader}, obtained by invoking its {@link
  78  * ClassLoader#getUnnamedModule() getUnnamedModule} method. All types that are


 352      */
 353     void implAddReads(Module other) {
 354         implAddReads(other, true);
 355     }
 356 
 357     /**
 358      * Updates this module to read another module without notifying the VM.
 359      *
 360      * @apiNote This method is for VM white-box testing.
 361      */
 362     void implAddReadsNoSync(Module other) {
 363         implAddReads(other, false);
 364     }
 365 
 366     /**
 367      * Makes the given {@code Module} readable to this module.
 368      *
 369      * If {@code syncVM} is {@code true} then the VM is notified.
 370      */
 371     private void implAddReads(Module other, boolean syncVM) {
 372         Objects.requireNonNull(other);
 373 
 374         // nothing to do
 375         if (other == this || !this.isNamed())
 376             return;
 377 
 378         // check if we already read this module
 379         Set<Module> reads = this.reads;
 380         if (reads != null && reads.contains(other))
 381             return;
 382 
 383         // update VM first, just in case it fails
 384         if (syncVM) {
 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     }

 395 
 396 
 397     // -- exported and open packages --
 398 
 399     // the packages are open to other modules, can be null
 400     // if the value contains EVERYONE_MODULE then the package is open to all
 401     private volatile Map<String, Set<Module>> openPackages;
 402 
 403     // the packages that are exported, can be null
 404     // if the value contains EVERYONE_MODULE then the package is exported to all
 405     private volatile Map<String, Set<Module>> exportedPackages;
 406 
 407     // additional exports or opens added at run-time
 408     // this module (1st key), other module (2nd key)
 409     // (package name, open?) (value)
 410     private static final WeakPairMap<Module, Module, Map<String, Boolean>>
 411         reflectivelyExports = new WeakPairMap<>();
 412 
 413 
 414     /**


 536         // all packages in open and automatic modules are open
 537         if (descriptor.isOpen() || descriptor.isAutomatic())
 538             return containsPackage(pn);
 539 
 540         // exported/opened via module declaration/descriptor
 541         if (isStaticallyExportedOrOpen(pn, other, open))
 542             return true;
 543 
 544         // exported via addExports/addOpens
 545         if (isReflectivelyExportedOrOpen(pn, other, open))
 546             return true;
 547 
 548         // not exported or open to other
 549         return false;
 550     }
 551 
 552     /**
 553      * Returns {@code true} if this module exports or opens a package to
 554      * the given module via its module declaration.
 555      */
 556     boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
 557         // package is open to everyone or <other>
 558         Map<String, Set<Module>> openPackages = this.openPackages;
 559         if (openPackages != null) {
 560             Set<Module> targets = openPackages.get(pn);
 561             if (targets != null) {
 562                 if (targets.contains(EVERYONE_MODULE))
 563                     return true;
 564                 if (other != EVERYONE_MODULE && targets.contains(other))
 565                     return true;
 566             }
 567         }
 568 
 569         if (!open) {
 570             // package is exported to everyone or <other>
 571             Map<String, Set<Module>> exportedPackages = this.exportedPackages;
 572             if (exportedPackages != null) {
 573                 Set<Module> targets = exportedPackages.get(pn);
 574                 if (targets != null) {
 575                     if (targets.contains(EVERYONE_MODULE))
 576                         return true;


 892 
 893     // -- packages --
 894 
 895     // Additional packages that are added to the module at run-time.
 896     private volatile Map<String, Boolean> extraPackages;
 897 
 898     private boolean containsPackage(String pn) {
 899         if (descriptor.packages().contains(pn))
 900             return true;
 901         Map<String, Boolean> extraPackages = this.extraPackages;
 902         if (extraPackages != null && extraPackages.containsKey(pn))
 903             return true;
 904         return false;
 905     }
 906 
 907 
 908     /**
 909      * Returns an array of the package names of the packages in this module.
 910      *
 911      * <p> For named modules, the returned array contains an element for each
 912      * package in the module. It may contain elements corresponding to packages
 913      * added to the module, <a href="Proxy.html#dynamicmodule">dynamic modules</a>
 914      * for example, after it was loaded.
 915      *
 916      * <p> For unnamed modules, this method is the equivalent to invoking the
 917      * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
 918      * this module's class loader and returning the array of package names. </p>
 919      *
 920      * <p> A package name appears at most once in the returned array. </p>
 921      *
 922      * @apiNote This method returns an array rather than a {@code Set} for
 923      * consistency with other {@code java.lang.reflect} types.
 924      *
 925      * @return an array of the package names of the packages in this module
 926      */
 927     public String[] getPackages() {
 928         if (isNamed()) {
 929 
 930             Set<String> packages = descriptor.packages();
 931             Map<String, Boolean> extraPackages = this.extraPackages;
 932             if (extraPackages == null) {
 933                 return packages.toArray(new String[0]);
 934             } else {
 935                 return Stream.concat(packages.stream(),
 936                                      extraPackages.keySet().stream())
 937                         .toArray(String[]::new);
 938             }
 939 
 940         } else {
 941             // unnamed module
 942             Stream<Package> packages;
 943             if (loader == null) {
 944                 packages = BootLoader.packages();
 945             } else {
 946                 packages = SharedSecrets.getJavaLangAccess().packages(loader);
 947             }
 948             return packages.map(Package::getName).toArray(String[]::new);
 949         }
 950     }
 951 
 952     /**
 953      * Add a package to this module.
 954      *
 955      * @apiNote This method is for Proxy use.
 956      */
 957     void addPackage(String pn) {
 958         implAddPackage(pn, true);
 959     }
 960 
 961     /**
 962      * Add a package to this module without notifying the VM.
 963      *
 964      * @apiNote This method is VM white-box testing.
 965      */
 966     void implAddPackageNoSync(String pn) {
 967         implAddPackage(pn.replace('/', '.'), false);
 968     }
 969 
 970     /**
 971      * Add a package to this module.
 972      *
 973      * If {@code syncVM} is {@code true} then the VM is notified. This method is
 974      * a no-op if this is an unnamed module or the module already contains the
 975      * package.
 976      *
 977      * @throws IllegalArgumentException if the package name is not legal
 978      * @throws IllegalStateException if the package is defined to another module
 979      */
 980     private void implAddPackage(String pn, boolean syncVM) {
 981         // no-op if unnamed module


1063                 // java.base is already defined to the VM
1064                 m = Object.class.getModule();
1065             } else {
1066                 m = new Module(layer, loader, descriptor, uri);
1067             }
1068             nameToModule.put(name, m);
1069             moduleToLoader.put(name, loader);
1070         }
1071 
1072         // setup readability and exports
1073         for (ResolvedModule resolvedModule : cf.modules()) {
1074             ModuleReference mref = resolvedModule.reference();
1075             ModuleDescriptor descriptor = mref.descriptor();
1076 
1077             String mn = descriptor.name();
1078             Module m = nameToModule.get(mn);
1079             assert m != null;
1080 
1081             // reads
1082             Set<Module> reads = new HashSet<>();




1083             for (ResolvedModule other : resolvedModule.reads()) {
1084                 Module m2 = null;
1085                 if (other.configuration() == cf) {
1086                     String dn = other.reference().descriptor().name();
1087                     m2 = nameToModule.get(dn);

1088                 } else {

1089                     for (Layer parent: layer.parents()) {
1090                         m2 = findModule(parent, other);
1091                         if (m2 != null)
1092                             break;
1093                     }
1094                 }
1095                 assert m2 != null;
1096 



1097                 reads.add(m2);
1098 
1099                 // update VM view
1100                 addReads0(m, m2);
1101             }
1102             m.reads = reads;
1103 
1104             // automatic modules read all unnamed modules
1105             if (descriptor.isAutomatic()) {
1106                 m.implAddReads(ALL_UNNAMED_MODULE, true);
1107             }
1108 
1109             // exports and opens
1110             initExportsAndOpens(descriptor, nameToModule, m);
1111         }
1112 
1113         // register the modules in the boot layer
1114         if (isBootLayer) {
1115             for (ResolvedModule resolvedModule : cf.modules()) {
1116                 ModuleReference mref = resolvedModule.reference();
1117                 ModuleDescriptor descriptor = mref.descriptor();
1118                 if (!descriptor.provides().isEmpty()) {
1119                     String name = descriptor.name();
1120                     Module m = nameToModule.get(name);
1121                     ClassLoader loader = moduleToLoader.get(name);
1122                     ServicesCatalog catalog;
1123                     if (loader == null) {
1124                         catalog = BootLoader.getServicesCatalog();
1125                     } else {
1126                         catalog = ServicesCatalog.getServicesCatalog(loader);
1127                     }
1128                     catalog.register(m);
1129                 }
1130             }


1142     /**
1143      * Find the runtime Module corresponding to the given ResolvedModule
1144      * in the given parent layer (or its parents).
1145      */
1146     private static Module findModule(Layer parent, ResolvedModule resolvedModule) {
1147         Configuration cf = resolvedModule.configuration();
1148         String dn = resolvedModule.name();
1149         return parent.layers()
1150                 .filter(l -> l.configuration() == cf)
1151                 .findAny()
1152                 .map(layer -> {
1153                     Optional<Module> om = layer.findModule(dn);
1154                     assert om.isPresent() : dn + " not found in layer";
1155                     Module m = om.get();
1156                     assert m.getLayer() == layer : m + " not in expected layer";
1157                     return m;
1158                 })
1159                 .orElse(null);
1160     }
1161 

1162     /**
1163      * Initialize the maps of exported and open packages for module m.
1164      */
1165     private static void initExportsAndOpens(ModuleDescriptor descriptor,

1166                                             Map<String, Module> nameToModule,
1167                                             Module m)
1168     {
1169         // The VM doesn't special case open or automatic modules so need to
1170         // export all packages

1171         if (descriptor.isOpen() || descriptor.isAutomatic()) {
1172             assert descriptor.opens().isEmpty();
1173             for (String source : descriptor.packages()) {
1174                 addExportsToAll0(m, source);
1175             }
1176             return;
1177         }
1178 
1179         Map<String, Set<Module>> openPackages = new HashMap<>();
1180         Map<String, Set<Module>> exportedPackages = new HashMap<>();
1181 
1182         // process the open packages first
1183         for (Opens opens : descriptor.opens()) {
1184             String source = opens.source();
1185 
1186             if (opens.isQualified()) {
1187                 // qualified opens
1188                 Set<Module> targets = new HashSet<>();
1189                 for (String target : opens.targets()) {
1190                     // only open to modules that are in this configuration
1191                     Module m2 = nameToModule.get(target);
1192                     if (m2 != null) {
1193                         addExports0(m, source, m2);
1194                         targets.add(m2);
1195                     }
1196                 }
1197                 if (!targets.isEmpty()) {
1198                     openPackages.put(source, targets);
1199                 }
1200             } else {
1201                 // unqualified opens
1202                 addExportsToAll0(m, source);
1203                 openPackages.put(source, EVERYONE_SET);
1204             }
1205         }
1206 
1207         // next the exports, skipping exports when the package is open
1208         for (Exports exports : descriptor.exports()) {
1209             String source = exports.source();
1210 
1211             // skip export if package is already open to everyone
1212             Set<Module> openToTargets = openPackages.get(source);
1213             if (openToTargets != null && openToTargets.contains(EVERYONE_MODULE))
1214                 continue;
1215 
1216             if (exports.isQualified()) {
1217                 // qualified exports
1218                 Set<Module> targets = new HashSet<>();
1219                 for (String target : exports.targets()) {
1220                     // only export to modules that are in this configuration
1221                     Module m2 = nameToModule.get(target);
1222                     if (m2 != null) {
1223                         // skip qualified export if already open to m2
1224                         if (openToTargets == null || !openToTargets.contains(m2)) {
1225                             addExports0(m, source, m2);
1226                             targets.add(m2);
1227                         }
1228                     }
1229                 }
1230                 if (!targets.isEmpty()) {
1231                     exportedPackages.put(source, targets);
1232                 }
1233 
1234             } else {
1235                 // unqualified exports
1236                 addExportsToAll0(m, source);
1237                 exportedPackages.put(source, EVERYONE_SET);
1238             }
1239         }
1240 
1241         if (!openPackages.isEmpty())
1242             m.openPackages = openPackages;
1243         if (!exportedPackages.isEmpty())
1244             m.exportedPackages = exportedPackages;
1245     }
1246 


























1247 
1248     // -- annotations --
1249 
1250     /**
1251      * {@inheritDoc}
1252      * This method returns {@code null} when invoked on an unnamed module.
1253      */
1254     @Override
1255     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
1256         return moduleInfoClass().getDeclaredAnnotation(annotationClass);
1257     }
1258 
1259     /**
1260      * {@inheritDoc}
1261      * This method returns an empty array when invoked on an unnamed module.
1262      */
1263     @Override
1264     public Annotation[] getAnnotations() {
1265         return moduleInfoClass().getAnnotations();
1266     }


1411      * <p> This method returns {@code null} if the resource is not in this
1412      * module, the resource is encapsulated and cannot be located by the caller,
1413      * or access to the resource is denied by the security manager. </p>
1414      *
1415      * @param  name
1416      *         The resource name
1417      *
1418      * @return An input stream for reading the resource or {@code null}
1419      *
1420      * @throws IOException
1421      *         If an I/O error occurs
1422      *
1423      * @see Class#getResourceAsStream(String)
1424      */
1425     @CallerSensitive
1426     public InputStream getResourceAsStream(String name) throws IOException {
1427         if (name.startsWith("/")) {
1428             name = name.substring(1);
1429         }
1430 
1431         if (isNamed() && !ResourceHelper.isSimpleResource(name)) {
1432             Module caller = Reflection.getCallerClass().getModule();
1433             if (caller != this && caller != Object.class.getModule()) {
1434                 // ignore packages added for proxies via addPackage
1435                 Set<String> packages = getDescriptor().packages();
1436                 String pn = ResourceHelper.getPackageName(name);
1437                 if (packages.contains(pn) && !isOpen(pn, caller)) {
1438                     // resource is in package not open to caller
1439                     return null;
1440                 }
1441             }
1442         }
1443 
1444         String mn = this.name;
1445 
1446         // special-case built-in class loaders to avoid URL connection
1447         if (loader == null) {
1448             return BootLoader.findResourceAsStream(mn, name);
1449         } else if (loader instanceof BuiltinClassLoader) {
1450             return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name);
1451         }
1452 
1453         // locate resource in module
1454         JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
1455         URL url = jla.findResource(loader, mn, name);
1456         if (url != null) {


1514             new JavaLangReflectModuleAccess() {
1515                 @Override
1516                 public Module defineUnnamedModule(ClassLoader loader) {
1517                     return new Module(loader);
1518                 }
1519                 @Override
1520                 public Module defineModule(ClassLoader loader,
1521                                            ModuleDescriptor descriptor,
1522                                            URI uri) {
1523                    return new Module(null, loader, descriptor, uri);
1524                 }
1525                 @Override
1526                 public void addReads(Module m1, Module m2) {
1527                     m1.implAddReads(m2, true);
1528                 }
1529                 @Override
1530                 public void addReadsAllUnnamed(Module m) {
1531                     m.implAddReads(Module.ALL_UNNAMED_MODULE);
1532                 }
1533                 @Override
1534                 public void addExports(Module m, String pn, Module other) {
1535                     m.implAddExportsOrOpens(pn, other, false, true);
1536                 }
1537                 @Override
1538                 public void addOpens(Module m, String pn, Module other) {
1539                     m.implAddExportsOrOpens(pn, other, true, true);
1540                 }
1541                 @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) {
1555                     m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true);
1556                 }
1557                 @Override
1558                 public void addUses(Module m, Class<?> service) {
1559                     m.implAddUses(service);
1560                 }
1561                 @Override
1562                 public void addPackage(Module m, String pn) {
1563                     m.implAddPackage(pn, true);
1564                 }
1565                 @Override
1566                 public ServicesCatalog getServicesCatalog(Layer layer) {
1567                     return layer.getServicesCatalog();
1568                 }
1569                 @Override
1570                 public Stream<Layer> layers(Layer layer) {
1571                     return layer.layers();
1572                 }
1573                 @Override
1574                 public Stream<Layer> layers(ClassLoader loader) {
1575                     return Layer.layers(loader);
1576                 }
1577                 @Override
1578                 public boolean isStaticallyExported(Module module, String pn, Module other) {
1579                     return module.isStaticallyExportedOrOpen(pn, other, false);
1580                 }
1581             });
1582     }
1583 }


  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.reflect;
  27 
  28 import java.io.IOException;
  29 import java.io.InputStream;
  30 import java.lang.annotation.Annotation;
  31 import java.lang.module.Configuration;
  32 import java.lang.module.ModuleReference;
  33 import java.lang.module.ModuleDescriptor;
  34 import java.lang.module.ModuleDescriptor.Exports;
  35 import java.lang.module.ModuleDescriptor.Opens;
  36 import java.lang.module.ModuleDescriptor.Version;
  37 import java.lang.module.ResolvedModule;
  38 import java.net.URI;
  39 import java.net.URL;
  40 import java.security.AccessController;
  41 import java.security.PrivilegedAction;
  42 import java.util.Collections;
  43 import java.util.HashMap;
  44 import java.util.HashSet;
  45 import java.util.List;
  46 import java.util.Map;
  47 import java.util.Objects;
  48 import java.util.Optional;
  49 import java.util.Set;
  50 import java.util.concurrent.ConcurrentHashMap;
  51 import java.util.function.Function;
  52 import java.util.stream.Stream;
  53 
  54 import jdk.internal.loader.BuiltinClassLoader;
  55 import jdk.internal.loader.BootLoader;

  56 import jdk.internal.misc.JavaLangAccess;
  57 import jdk.internal.misc.JavaLangReflectModuleAccess;
  58 import jdk.internal.misc.SharedSecrets;
  59 import jdk.internal.module.ServicesCatalog;
  60 import jdk.internal.module.Resources;
  61 import jdk.internal.org.objectweb.asm.AnnotationVisitor;
  62 import jdk.internal.org.objectweb.asm.Attribute;
  63 import jdk.internal.org.objectweb.asm.ClassReader;
  64 import jdk.internal.org.objectweb.asm.ClassVisitor;
  65 import jdk.internal.org.objectweb.asm.ClassWriter;
  66 import jdk.internal.org.objectweb.asm.Opcodes;
  67 import jdk.internal.reflect.CallerSensitive;
  68 import jdk.internal.reflect.Reflection;
  69 import sun.security.util.SecurityConstants;
  70 
  71 /**
  72  * Represents a run-time module, either {@link #isNamed() named} or unnamed.
  73  *
  74  * <p> Named modules have a {@link #getName() name} and are constructed by the
  75  * Java Virtual Machine when a graph of modules is defined to the Java virtual
  76  * machine to create a module {@link Layer Layer}. </p>
  77  *
  78  * <p> An unnamed module does not have a name. There is an unnamed module for
  79  * each {@link ClassLoader ClassLoader}, obtained by invoking its {@link
  80  * ClassLoader#getUnnamedModule() getUnnamedModule} method. All types that are


 354      */
 355     void implAddReads(Module other) {
 356         implAddReads(other, true);
 357     }
 358 
 359     /**
 360      * Updates this module to read another module without notifying the VM.
 361      *
 362      * @apiNote This method is for VM white-box testing.
 363      */
 364     void implAddReadsNoSync(Module other) {
 365         implAddReads(other, false);
 366     }
 367 
 368     /**
 369      * Makes the given {@code Module} readable to this module.
 370      *
 371      * If {@code syncVM} is {@code true} then the VM is notified.
 372      */
 373     private void implAddReads(Module other, boolean syncVM) {
 374         if (!canRead(other)) {










 375             // update VM first, just in case it fails
 376             if (syncVM) {
 377                 if (other == ALL_UNNAMED_MODULE) {
 378                     addReads0(this, null);
 379                 } else {
 380                     addReads0(this, other);
 381                 }
 382             }
 383 
 384             // add reflective read
 385             reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
 386         }
 387     }
 388 
 389 
 390     // -- exported and open packages --
 391 
 392     // the packages are open to other modules, can be null
 393     // if the value contains EVERYONE_MODULE then the package is open to all
 394     private volatile Map<String, Set<Module>> openPackages;
 395 
 396     // the packages that are exported, can be null
 397     // if the value contains EVERYONE_MODULE then the package is exported to all
 398     private volatile Map<String, Set<Module>> exportedPackages;
 399 
 400     // additional exports or opens added at run-time
 401     // this module (1st key), other module (2nd key)
 402     // (package name, open?) (value)
 403     private static final WeakPairMap<Module, Module, Map<String, Boolean>>
 404         reflectivelyExports = new WeakPairMap<>();
 405 
 406 
 407     /**


 529         // all packages in open and automatic modules are open
 530         if (descriptor.isOpen() || descriptor.isAutomatic())
 531             return containsPackage(pn);
 532 
 533         // exported/opened via module declaration/descriptor
 534         if (isStaticallyExportedOrOpen(pn, other, open))
 535             return true;
 536 
 537         // exported via addExports/addOpens
 538         if (isReflectivelyExportedOrOpen(pn, other, open))
 539             return true;
 540 
 541         // not exported or open to other
 542         return false;
 543     }
 544 
 545     /**
 546      * Returns {@code true} if this module exports or opens a package to
 547      * the given module via its module declaration.
 548      */
 549     private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
 550         // package is open to everyone or <other>
 551         Map<String, Set<Module>> openPackages = this.openPackages;
 552         if (openPackages != null) {
 553             Set<Module> targets = openPackages.get(pn);
 554             if (targets != null) {
 555                 if (targets.contains(EVERYONE_MODULE))
 556                     return true;
 557                 if (other != EVERYONE_MODULE && targets.contains(other))
 558                     return true;
 559             }
 560         }
 561 
 562         if (!open) {
 563             // package is exported to everyone or <other>
 564             Map<String, Set<Module>> exportedPackages = this.exportedPackages;
 565             if (exportedPackages != null) {
 566                 Set<Module> targets = exportedPackages.get(pn);
 567                 if (targets != null) {
 568                     if (targets.contains(EVERYONE_MODULE))
 569                         return true;


 885 
 886     // -- packages --
 887 
 888     // Additional packages that are added to the module at run-time.
 889     private volatile Map<String, Boolean> extraPackages;
 890 
 891     private boolean containsPackage(String pn) {
 892         if (descriptor.packages().contains(pn))
 893             return true;
 894         Map<String, Boolean> extraPackages = this.extraPackages;
 895         if (extraPackages != null && extraPackages.containsKey(pn))
 896             return true;
 897         return false;
 898     }
 899 
 900 
 901     /**
 902      * Returns an array of the package names of the packages in this module.
 903      *
 904      * <p> For named modules, the returned array contains an element for each
 905      * package in the module. </p>


 906      *
 907      * <p> For unnamed modules, this method is the equivalent to invoking the
 908      * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
 909      * this module's class loader and returning the array of package names. </p>
 910      *
 911      * <p> A package name appears at most once in the returned array. </p>
 912      *
 913      * @apiNote This method returns an array rather than a {@code Set} for
 914      * consistency with other {@code java.lang.reflect} types.
 915      *
 916      * @return an array of the package names of the packages in this module
 917      */
 918     public String[] getPackages() {
 919         if (isNamed()) {
 920 
 921             Set<String> packages = descriptor.packages();
 922             Map<String, Boolean> extraPackages = this.extraPackages;
 923             if (extraPackages == null) {
 924                 return packages.toArray(new String[0]);
 925             } else {
 926                 return Stream.concat(packages.stream(),
 927                                      extraPackages.keySet().stream())
 928                         .toArray(String[]::new);
 929             }
 930 
 931         } else {
 932             // unnamed module
 933             Stream<Package> packages;
 934             if (loader == null) {
 935                 packages = BootLoader.packages();
 936             } else {
 937                 packages = SharedSecrets.getJavaLangAccess().packages(loader);
 938             }
 939             return packages.map(Package::getName).toArray(String[]::new);
 940         }
 941     }
 942 
 943     /**









 944      * Add a package to this module without notifying the VM.
 945      *
 946      * @apiNote This method is VM white-box testing.
 947      */
 948     void implAddPackageNoSync(String pn) {
 949         implAddPackage(pn.replace('/', '.'), false);
 950     }
 951 
 952     /**
 953      * Add a package to this module.
 954      *
 955      * If {@code syncVM} is {@code true} then the VM is notified. This method is
 956      * a no-op if this is an unnamed module or the module already contains the
 957      * package.
 958      *
 959      * @throws IllegalArgumentException if the package name is not legal
 960      * @throws IllegalStateException if the package is defined to another module
 961      */
 962     private void implAddPackage(String pn, boolean syncVM) {
 963         // no-op if unnamed module


1045                 // java.base is already defined to the VM
1046                 m = Object.class.getModule();
1047             } else {
1048                 m = new Module(layer, loader, descriptor, uri);
1049             }
1050             nameToModule.put(name, m);
1051             moduleToLoader.put(name, loader);
1052         }
1053 
1054         // setup readability and exports
1055         for (ResolvedModule resolvedModule : cf.modules()) {
1056             ModuleReference mref = resolvedModule.reference();
1057             ModuleDescriptor descriptor = mref.descriptor();
1058 
1059             String mn = descriptor.name();
1060             Module m = nameToModule.get(mn);
1061             assert m != null;
1062 
1063             // reads
1064             Set<Module> reads = new HashSet<>();
1065 
1066             // name -> source Module when in parent layer
1067             Map<String, Module> nameToSource = Collections.emptyMap();
1068 
1069             for (ResolvedModule other : resolvedModule.reads()) {
1070                 Module m2 = null;
1071                 if (other.configuration() == cf) {
1072                     // this configuration
1073                     m2 = nameToModule.get(other.name());
1074                     assert m2 != null;
1075                 } else {
1076                     // parent layer
1077                     for (Layer parent: layer.parents()) {
1078                         m2 = findModule(parent, other);
1079                         if (m2 != null)
1080                             break;
1081                     }

1082                     assert m2 != null;
1083                     if (nameToSource.isEmpty())
1084                         nameToSource = new HashMap<>();
1085                     nameToSource.put(other.name(), m2);
1086                 }
1087                 reads.add(m2);
1088 
1089                 // update VM view
1090                 addReads0(m, m2);
1091             }
1092             m.reads = reads;
1093 
1094             // automatic modules read all unnamed modules
1095             if (descriptor.isAutomatic()) {
1096                 m.implAddReads(ALL_UNNAMED_MODULE, true);
1097             }
1098 
1099             // exports and opens
1100             initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
1101         }
1102 
1103         // register the modules in the boot layer
1104         if (isBootLayer) {
1105             for (ResolvedModule resolvedModule : cf.modules()) {
1106                 ModuleReference mref = resolvedModule.reference();
1107                 ModuleDescriptor descriptor = mref.descriptor();
1108                 if (!descriptor.provides().isEmpty()) {
1109                     String name = descriptor.name();
1110                     Module m = nameToModule.get(name);
1111                     ClassLoader loader = moduleToLoader.get(name);
1112                     ServicesCatalog catalog;
1113                     if (loader == null) {
1114                         catalog = BootLoader.getServicesCatalog();
1115                     } else {
1116                         catalog = ServicesCatalog.getServicesCatalog(loader);
1117                     }
1118                     catalog.register(m);
1119                 }
1120             }


1132     /**
1133      * Find the runtime Module corresponding to the given ResolvedModule
1134      * in the given parent layer (or its parents).
1135      */
1136     private static Module findModule(Layer parent, ResolvedModule resolvedModule) {
1137         Configuration cf = resolvedModule.configuration();
1138         String dn = resolvedModule.name();
1139         return parent.layers()
1140                 .filter(l -> l.configuration() == cf)
1141                 .findAny()
1142                 .map(layer -> {
1143                     Optional<Module> om = layer.findModule(dn);
1144                     assert om.isPresent() : dn + " not found in layer";
1145                     Module m = om.get();
1146                     assert m.getLayer() == layer : m + " not in expected layer";
1147                     return m;
1148                 })
1149                 .orElse(null);
1150     }
1151 
1152 
1153     /**
1154      * Initialize the maps of exported and open packages for module m.
1155      */
1156     private static void initExportsAndOpens(Module m,
1157                                             Map<String, Module> nameToSource,
1158                                             Map<String, Module> nameToModule,
1159                                             List<Layer> parents) {

1160         // The VM doesn't special case open or automatic modules so need to
1161         // export all packages
1162         ModuleDescriptor descriptor = m.getDescriptor();
1163         if (descriptor.isOpen() || descriptor.isAutomatic()) {
1164             assert descriptor.opens().isEmpty();
1165             for (String source : descriptor.packages()) {
1166                 addExportsToAll0(m, source);
1167             }
1168             return;
1169         }
1170 
1171         Map<String, Set<Module>> openPackages = new HashMap<>();
1172         Map<String, Set<Module>> exportedPackages = new HashMap<>();
1173 
1174         // process the open packages first
1175         for (Opens opens : descriptor.opens()) {
1176             String source = opens.source();
1177 
1178             if (opens.isQualified()) {
1179                 // qualified opens
1180                 Set<Module> targets = new HashSet<>();
1181                 for (String target : opens.targets()) {
1182                     Module m2 = findModule(target, nameToSource, nameToModule, parents);

1183                     if (m2 != null) {
1184                         addExports0(m, source, m2);
1185                         targets.add(m2);
1186                     }
1187                 }
1188                 if (!targets.isEmpty()) {
1189                     openPackages.put(source, targets);
1190                 }
1191             } else {
1192                 // unqualified opens
1193                 addExportsToAll0(m, source);
1194                 openPackages.put(source, EVERYONE_SET);
1195             }
1196         }
1197 
1198         // next the exports, skipping exports when the package is open
1199         for (Exports exports : descriptor.exports()) {
1200             String source = exports.source();
1201 
1202             // skip export if package is already open to everyone
1203             Set<Module> openToTargets = openPackages.get(source);
1204             if (openToTargets != null && openToTargets.contains(EVERYONE_MODULE))
1205                 continue;
1206 
1207             if (exports.isQualified()) {
1208                 // qualified exports
1209                 Set<Module> targets = new HashSet<>();
1210                 for (String target : exports.targets()) {
1211                     Module m2 = findModule(target, nameToSource, nameToModule, parents);

1212                     if (m2 != null) {
1213                         // skip qualified export if already open to m2
1214                         if (openToTargets == null || !openToTargets.contains(m2)) {
1215                             addExports0(m, source, m2);
1216                             targets.add(m2);
1217                         }
1218                     }
1219                 }
1220                 if (!targets.isEmpty()) {
1221                     exportedPackages.put(source, targets);
1222                 }
1223 
1224             } else {
1225                 // unqualified exports
1226                 addExportsToAll0(m, source);
1227                 exportedPackages.put(source, EVERYONE_SET);
1228             }
1229         }
1230 
1231         if (!openPackages.isEmpty())
1232             m.openPackages = openPackages;
1233         if (!exportedPackages.isEmpty())
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;
1261     }
1262 
1263 
1264     // -- annotations --
1265 
1266     /**
1267      * {@inheritDoc}
1268      * This method returns {@code null} when invoked on an unnamed module.
1269      */
1270     @Override
1271     public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
1272         return moduleInfoClass().getDeclaredAnnotation(annotationClass);
1273     }
1274 
1275     /**
1276      * {@inheritDoc}
1277      * This method returns an empty array when invoked on an unnamed module.
1278      */
1279     @Override
1280     public Annotation[] getAnnotations() {
1281         return moduleInfoClass().getAnnotations();
1282     }


1427      * <p> This method returns {@code null} if the resource is not in this
1428      * module, the resource is encapsulated and cannot be located by the caller,
1429      * or access to the resource is denied by the security manager. </p>
1430      *
1431      * @param  name
1432      *         The resource name
1433      *
1434      * @return An input stream for reading the resource or {@code null}
1435      *
1436      * @throws IOException
1437      *         If an I/O error occurs
1438      *
1439      * @see Class#getResourceAsStream(String)
1440      */
1441     @CallerSensitive
1442     public InputStream getResourceAsStream(String name) throws IOException {
1443         if (name.startsWith("/")) {
1444             name = name.substring(1);
1445         }
1446 
1447         if (isNamed() && Resources.canEncapsulate(name)) {
1448             Module caller = Reflection.getCallerClass().getModule();
1449             if (caller != this && caller != Object.class.getModule()) {
1450                 // ignore packages added for proxies via addPackage
1451                 Set<String> packages = getDescriptor().packages();
1452                 String pn = Resources.toPackageName(name);
1453                 if (packages.contains(pn) && !isOpen(pn, caller)) {
1454                     // resource is in package not open to caller
1455                     return null;
1456                 }
1457             }
1458         }
1459 
1460         String mn = this.name;
1461 
1462         // special-case built-in class loaders to avoid URL connection
1463         if (loader == null) {
1464             return BootLoader.findResourceAsStream(mn, name);
1465         } else if (loader instanceof BuiltinClassLoader) {
1466             return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name);
1467         }
1468 
1469         // locate resource in module
1470         JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
1471         URL url = jla.findResource(loader, mn, name);
1472         if (url != null) {


1530             new JavaLangReflectModuleAccess() {
1531                 @Override
1532                 public Module defineUnnamedModule(ClassLoader loader) {
1533                     return new Module(loader);
1534                 }
1535                 @Override
1536                 public Module defineModule(ClassLoader loader,
1537                                            ModuleDescriptor descriptor,
1538                                            URI uri) {
1539                    return new Module(null, loader, descriptor, uri);
1540                 }
1541                 @Override
1542                 public void addReads(Module m1, Module m2) {
1543                     m1.implAddReads(m2, true);
1544                 }
1545                 @Override
1546                 public void addReadsAllUnnamed(Module m) {
1547                     m.implAddReads(Module.ALL_UNNAMED_MODULE);
1548                 }
1549                 @Override
1550                 public void addExports(Module m, String pn) {
1551                     m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
1552                 }
1553                 @Override
1554                 public void addExports(Module m, String pn, Module other) {
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);
1564                 }
1565                 @Override
1566                 public void addOpens(Module m, String pn, Module other) {
1567                     m.implAddExportsOrOpens(pn, other, true, true);
1568                 }
1569                 @Override
1570                 public void addOpensToAllUnnamed(Module m, String pn) {
1571                     m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true);
1572                 }
1573                 @Override
1574                 public void addUses(Module m, Class<?> service) {
1575                     m.implAddUses(service);
1576                 }
1577                 @Override




1578                 public ServicesCatalog getServicesCatalog(Layer layer) {
1579                     return layer.getServicesCatalog();
1580                 }
1581                 @Override
1582                 public Stream<Layer> layers(Layer layer) {
1583                     return layer.layers();
1584                 }
1585                 @Override
1586                 public Stream<Layer> layers(ClassLoader loader) {
1587                     return Layer.layers(loader);
1588                 }




1589             });
1590     }
1591 }
< prev index next >