< prev index next >
src/java.base/share/classes/java/lang/reflect/Module.java
Print this page
*** 37,63 ****
import java.lang.module.ResolvedModule;
import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Stream;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.BootLoader;
- import jdk.internal.loader.ResourceHelper;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.JavaLangReflectModuleAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.ServicesCatalog;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
--- 37,65 ----
import java.lang.module.ResolvedModule;
import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
+ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Stream;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.BootLoader;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.JavaLangReflectModuleAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.ServicesCatalog;
+ import jdk.internal.module.Resources;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
*** 367,387 ****
* Makes the given {@code Module} readable to this module.
*
* If {@code syncVM} is {@code true} then the VM is notified.
*/
private void implAddReads(Module other, boolean syncVM) {
! Objects.requireNonNull(other);
!
! // nothing to do
! if (other == this || !this.isNamed())
! return;
!
! // check if we already read this module
! Set<Module> reads = this.reads;
! if (reads != null && reads.contains(other))
! return;
!
// update VM first, just in case it fails
if (syncVM) {
if (other == ALL_UNNAMED_MODULE) {
addReads0(this, null);
} else {
--- 369,379 ----
* Makes the given {@code Module} readable to this module.
*
* If {@code syncVM} is {@code true} then the VM is notified.
*/
private void implAddReads(Module other, boolean syncVM) {
! if (!canRead(other)) {
// update VM first, just in case it fails
if (syncVM) {
if (other == ALL_UNNAMED_MODULE) {
addReads0(this, null);
} else {
*** 390,399 ****
--- 382,392 ----
}
// add reflective read
reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
}
+ }
// -- exported and open packages --
// the packages are open to other modules, can be null
*** 551,561 ****
/**
* Returns {@code true} if this module exports or opens a package to
* the given module via its module declaration.
*/
! boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
// package is open to everyone or <other>
Map<String, Set<Module>> openPackages = this.openPackages;
if (openPackages != null) {
Set<Module> targets = openPackages.get(pn);
if (targets != null) {
--- 544,554 ----
/**
* Returns {@code true} if this module exports or opens a package to
* the given module via its module declaration.
*/
! private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
// package is open to everyone or <other>
Map<String, Set<Module>> openPackages = this.openPackages;
if (openPackages != null) {
Set<Module> targets = openPackages.get(pn);
if (targets != null) {
*** 907,919 ****
/**
* Returns an array of the package names of the packages in this module.
*
* <p> For named modules, the returned array contains an element for each
! * package in the module. It may contain elements corresponding to packages
! * added to the module, <a href="Proxy.html#dynamicmodule">dynamic modules</a>
! * for example, after it was loaded.
*
* <p> For unnamed modules, this method is the equivalent to invoking the
* {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
* this module's class loader and returning the array of package names. </p>
*
--- 900,910 ----
/**
* Returns an array of the package names of the packages in this module.
*
* <p> For named modules, the returned array contains an element for each
! * package in the module. </p>
*
* <p> For unnamed modules, this method is the equivalent to invoking the
* {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
* this module's class loader and returning the array of package names. </p>
*
*** 948,966 ****
return packages.map(Package::getName).toArray(String[]::new);
}
}
/**
- * Add a package to this module.
- *
- * @apiNote This method is for Proxy use.
- */
- void addPackage(String pn) {
- implAddPackage(pn, true);
- }
-
- /**
* Add a package to this module without notifying the VM.
*
* @apiNote This method is VM white-box testing.
*/
void implAddPackageNoSync(String pn) {
--- 939,948 ----
*** 1078,1101 ****
Module m = nameToModule.get(mn);
assert m != null;
// reads
Set<Module> reads = new HashSet<>();
for (ResolvedModule other : resolvedModule.reads()) {
Module m2 = null;
if (other.configuration() == cf) {
! String dn = other.reference().descriptor().name();
! m2 = nameToModule.get(dn);
} else {
for (Layer parent: layer.parents()) {
m2 = findModule(parent, other);
if (m2 != null)
break;
}
- }
assert m2 != null;
!
reads.add(m2);
// update VM view
addReads0(m, m2);
}
--- 1060,1091 ----
Module m = nameToModule.get(mn);
assert m != null;
// reads
Set<Module> reads = new HashSet<>();
+
+ // name -> source Module when in parent layer
+ Map<String, Module> nameToSource = Collections.emptyMap();
+
for (ResolvedModule other : resolvedModule.reads()) {
Module m2 = null;
if (other.configuration() == cf) {
! // this configuration
! m2 = nameToModule.get(other.name());
! assert m2 != null;
} else {
+ // parent layer
for (Layer parent: layer.parents()) {
m2 = findModule(parent, other);
if (m2 != null)
break;
}
assert m2 != null;
! if (nameToSource.isEmpty())
! nameToSource = new HashMap<>();
! nameToSource.put(other.name(), m2);
! }
reads.add(m2);
// update VM view
addReads0(m, m2);
}
*** 1105,1115 ****
if (descriptor.isAutomatic()) {
m.implAddReads(ALL_UNNAMED_MODULE, true);
}
// exports and opens
! initExportsAndOpens(descriptor, nameToModule, m);
}
// register the modules in the boot layer
if (isBootLayer) {
for (ResolvedModule resolvedModule : cf.modules()) {
--- 1095,1105 ----
if (descriptor.isAutomatic()) {
m.implAddReads(ALL_UNNAMED_MODULE, true);
}
// exports and opens
! initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
}
// register the modules in the boot layer
if (isBootLayer) {
for (ResolvedModule resolvedModule : cf.modules()) {
*** 1157,1175 ****
return m;
})
.orElse(null);
}
/**
* Initialize the maps of exported and open packages for module m.
*/
! private static void initExportsAndOpens(ModuleDescriptor descriptor,
Map<String, Module> nameToModule,
! Module m)
! {
// The VM doesn't special case open or automatic modules so need to
// export all packages
if (descriptor.isOpen() || descriptor.isAutomatic()) {
assert descriptor.opens().isEmpty();
for (String source : descriptor.packages()) {
addExportsToAll0(m, source);
}
--- 1147,1167 ----
return m;
})
.orElse(null);
}
+
/**
* Initialize the maps of exported and open packages for module m.
*/
! private static void initExportsAndOpens(Module m,
! Map<String, Module> nameToSource,
Map<String, Module> nameToModule,
! List<Layer> parents) {
// The VM doesn't special case open or automatic modules so need to
// export all packages
+ ModuleDescriptor descriptor = m.getDescriptor();
if (descriptor.isOpen() || descriptor.isAutomatic()) {
assert descriptor.opens().isEmpty();
for (String source : descriptor.packages()) {
addExportsToAll0(m, source);
}
*** 1185,1196 ****
if (opens.isQualified()) {
// qualified opens
Set<Module> targets = new HashSet<>();
for (String target : opens.targets()) {
! // only open to modules that are in this configuration
! Module m2 = nameToModule.get(target);
if (m2 != null) {
addExports0(m, source, m2);
targets.add(m2);
}
}
--- 1177,1187 ----
if (opens.isQualified()) {
// qualified opens
Set<Module> targets = new HashSet<>();
for (String target : opens.targets()) {
! Module m2 = findModule(target, nameToSource, nameToModule, parents);
if (m2 != null) {
addExports0(m, source, m2);
targets.add(m2);
}
}
*** 1215,1226 ****
if (exports.isQualified()) {
// qualified exports
Set<Module> targets = new HashSet<>();
for (String target : exports.targets()) {
! // only export to modules that are in this configuration
! Module m2 = nameToModule.get(target);
if (m2 != null) {
// skip qualified export if already open to m2
if (openToTargets == null || !openToTargets.contains(m2)) {
addExports0(m, source, m2);
targets.add(m2);
--- 1206,1216 ----
if (exports.isQualified()) {
// qualified exports
Set<Module> targets = new HashSet<>();
for (String target : exports.targets()) {
! Module m2 = findModule(target, nameToSource, nameToModule, parents);
if (m2 != null) {
// skip qualified export if already open to m2
if (openToTargets == null || !openToTargets.contains(m2)) {
addExports0(m, source, m2);
targets.add(m2);
*** 1242,1251 ****
--- 1232,1267 ----
m.openPackages = openPackages;
if (!exportedPackages.isEmpty())
m.exportedPackages = exportedPackages;
}
+ /**
+ * Find the runtime Module with the given name. The module name is the
+ * name of a target module in a qualified exports or opens directive.
+ *
+ * @param target The target module to find
+ * @param nameToSource The modules in parent layers that are read
+ * @param nameToModule The modules in the layer under construction
+ * @param parents The parent layers
+ */
+ private static Module findModule(String target,
+ Map<String, Module> nameToSource,
+ Map<String, Module> nameToModule,
+ List<Layer> parents) {
+ Module m = nameToSource.get(target);
+ if (m == null) {
+ m = nameToModule.get(target);
+ if (m == null) {
+ for (Layer parent : parents) {
+ m = parent.findModule(target).orElse(null);
+ if (m != null) break;
+ }
+ }
+ }
+ return m;
+ }
+
// -- annotations --
/**
* {@inheritDoc}
*** 1426,1441 ****
public InputStream getResourceAsStream(String name) throws IOException {
if (name.startsWith("/")) {
name = name.substring(1);
}
! if (isNamed() && !ResourceHelper.isSimpleResource(name)) {
Module caller = Reflection.getCallerClass().getModule();
if (caller != this && caller != Object.class.getModule()) {
// ignore packages added for proxies via addPackage
Set<String> packages = getDescriptor().packages();
! String pn = ResourceHelper.getPackageName(name);
if (packages.contains(pn) && !isOpen(pn, caller)) {
// resource is in package not open to caller
return null;
}
}
--- 1442,1457 ----
public InputStream getResourceAsStream(String name) throws IOException {
if (name.startsWith("/")) {
name = name.substring(1);
}
! if (isNamed() && Resources.canEncapsulate(name)) {
Module caller = Reflection.getCallerClass().getModule();
if (caller != this && caller != Object.class.getModule()) {
// ignore packages added for proxies via addPackage
Set<String> packages = getDescriptor().packages();
! String pn = Resources.toPackageName(name);
if (packages.contains(pn) && !isOpen(pn, caller)) {
// resource is in package not open to caller
return null;
}
}
*** 1529,1570 ****
@Override
public void addReadsAllUnnamed(Module m) {
m.implAddReads(Module.ALL_UNNAMED_MODULE);
}
@Override
! public void addExports(Module m, String pn, Module other) {
! m.implAddExportsOrOpens(pn, other, false, true);
}
@Override
! public void addOpens(Module m, String pn, Module other) {
! m.implAddExportsOrOpens(pn, other, true, true);
}
@Override
! public void addExportsToAll(Module m, String pn) {
! m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
}
@Override
! public void addOpensToAll(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true);
}
@Override
! public void addExportsToAllUnnamed(Module m, String pn) {
! m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true);
}
@Override
public void addOpensToAllUnnamed(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true);
}
@Override
public void addUses(Module m, Class<?> service) {
m.implAddUses(service);
}
@Override
- public void addPackage(Module m, String pn) {
- m.implAddPackage(pn, true);
- }
- @Override
public ServicesCatalog getServicesCatalog(Layer layer) {
return layer.getServicesCatalog();
}
@Override
public Stream<Layer> layers(Layer layer) {
--- 1545,1582 ----
@Override
public void addReadsAllUnnamed(Module m) {
m.implAddReads(Module.ALL_UNNAMED_MODULE);
}
@Override
! public void addExports(Module m, String pn) {
! m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
}
@Override
! public void addExports(Module m, String pn, Module other) {
! m.implAddExportsOrOpens(pn, other, false, true);
}
@Override
! public void addExportsToAllUnnamed(Module m, String pn) {
! m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true);
}
@Override
! public void addOpens(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true);
}
@Override
! public void addOpens(Module m, String pn, Module other) {
! m.implAddExportsOrOpens(pn, other, true, true);
}
@Override
public void addOpensToAllUnnamed(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true);
}
@Override
public void addUses(Module m, Class<?> service) {
m.implAddUses(service);
}
@Override
public ServicesCatalog getServicesCatalog(Layer layer) {
return layer.getServicesCatalog();
}
@Override
public Stream<Layer> layers(Layer layer) {
*** 1572,1583 ****
}
@Override
public Stream<Layer> layers(ClassLoader loader) {
return Layer.layers(loader);
}
- @Override
- public boolean isStaticallyExported(Module module, String pn, Module other) {
- return module.isStaticallyExportedOrOpen(pn, other, false);
- }
});
}
}
--- 1584,1591 ----
< prev index next >