< prev index next >
src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
Print this page
*** 24,42 ****
--- 24,45 ----
*/
package jdk.internal.module;
import java.io.File;
+ import java.io.IOException;
import java.io.PrintStream;
+ import java.io.UncheckedIOException;
import java.lang.module.Configuration;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.lang.reflect.Layer;
import java.lang.reflect.Module;
import java.net.URI;
+ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
*** 44,58 ****
--- 47,63 ----
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
+ import java.util.stream.Stream;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.perf.PerfCounter;
+ import jdk.internal.reflect.Reflection;
/**
* Initializes/boots the module system.
*
* The {@link #boot() boot} method is called early in the startup to initialize
*** 193,203 ****
// If there is no initial module specified then assume that the initial
// module is the unnamed module of the application class loader. This
// is implemented by resolving "java.se" and all (non-java.*) modules
// that export an API. If "java.se" is not observable then all java.*
! // modules are resolved.
if (mainModule == null || addAllDefaultModules) {
boolean hasJava = false;
if (systemModules.find(JAVA_SE).isPresent()) {
// java.se is a system module
if (finder == systemModules || finder.find(JAVA_SE).isPresent()) {
--- 198,210 ----
// If there is no initial module specified then assume that the initial
// module is the unnamed module of the application class loader. This
// is implemented by resolving "java.se" and all (non-java.*) modules
// that export an API. If "java.se" is not observable then all java.*
! // modules are resolved. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT
! // bit set in their ModuleResolution attribute flags are excluded from
! // the default set of roots.
if (mainModule == null || addAllDefaultModules) {
boolean hasJava = false;
if (systemModules.find(JAVA_SE).isPresent()) {
// java.se is a system module
if (finder == systemModules || finder.find(JAVA_SE).isPresent()) {
*** 210,219 ****
--- 217,229 ----
for (ModuleReference mref : systemModules.findAll()) {
String mn = mref.descriptor().name();
if (hasJava && mn.startsWith("java."))
continue;
+ if (ModuleResolution.doNotResolveByDefault(mref))
+ continue;
+
// add as root if observable and exports at least one package
if ((finder == systemModules || finder.find(mn).isPresent())) {
ModuleDescriptor descriptor = mref.descriptor();
for (ModuleDescriptor.Exports e : descriptor.exports()) {
if (!e.isQualified()) {
*** 229,238 ****
--- 239,249 ----
// modules will be resolved.
if (addAllSystemModules) {
ModuleFinder f = finder; // observable modules
systemModules.findAll()
.stream()
+ .filter(mref -> !ModuleResolution.doNotResolveByDefault(mref))
.map(ModuleReference::descriptor)
.map(ModuleDescriptor::name)
.filter(mn -> f.find(mn).isPresent()) // observable
.forEach(mn -> roots.add(mn));
}
*** 275,284 ****
--- 286,297 ----
traceOutput);
// time to create configuration
PerfCounters.resolveTime.addElapsedTimeFrom(t3);
+ // check module names and incubating status
+ checkModuleNamesAndStatus(cf);
// mapping of modules to class loaders
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
// check that all modules to be mapped to the boot loader will be
*** 494,521 ****
prefix = "jdk.module.addopens.";
Map<String, List<String>> extraOpens = decode(prefix);
if (!extraOpens.isEmpty()) {
addExtraExportsOrOpens(bootLayer, extraOpens, true);
}
}
private static void addExtraExportsOrOpens(Layer bootLayer,
Map<String, List<String>> map,
boolean opens)
{
for (Map.Entry<String, List<String>> e : map.entrySet()) {
// the key is $MODULE/$PACKAGE
String key = e.getKey();
String[] s = key.split("/");
if (s.length != 2)
! fail("Unable to parse: " + key);
String mn = s[0];
String pn = s[1];
if (mn.isEmpty() || pn.isEmpty())
! fail("Module and package name must be specified:" + key);
// The exporting module is in the boot layer
Module m;
Optional<Module> om = bootLayer.findModule(mn);
if (!om.isPresent()) {
--- 507,575 ----
prefix = "jdk.module.addopens.";
Map<String, List<String>> extraOpens = decode(prefix);
if (!extraOpens.isEmpty()) {
addExtraExportsOrOpens(bootLayer, extraOpens, true);
}
+
+ // DEBUG_ADD_OPENS is for debugging purposes only
+ String home = System.getProperty("java.home");
+ Path file = Paths.get(home, "conf", "DEBUG_ADD_OPENS");
+ if (Files.exists(file)) {
+ warn(file + " detected; may break encapsulation");
+ try (Stream<String> lines = Files.lines(file)) {
+ lines.map(line -> line.trim())
+ .filter(line -> (!line.isEmpty() && !line.startsWith("#")))
+ .forEach(line -> {
+ String[] s = line.split("/");
+ if (s.length != 2) {
+ fail("Unable to parse as <module>/<package>: " + line);
+ } else {
+ String mn = s[0];
+ String pkg = s[1];
+ openPackage(bootLayer, mn, pkg);
+ }
+ });
+ } catch (IOException ioe) {
+ throw new UncheckedIOException(ioe);
+ }
+ Reflection.enableStackTraces();
+ }
+ }
+
+ private static void openPackage(Layer bootLayer, String mn, String pkg) {
+ if (mn.equals("ALL-RESOLVED") && pkg.equals("ALL-PACKAGES")) {
+ bootLayer.modules().stream().forEach(m ->
+ m.getDescriptor().packages().forEach(pn -> openPackage(m, pn)));
+ } else {
+ bootLayer.findModule(mn)
+ .filter(m -> m.getDescriptor().packages().contains(pkg))
+ .ifPresent(m -> openPackage(m, pkg));
+ }
+ }
+
+ private static void openPackage(Module m, String pn) {
+ Modules.addOpensToAllUnnamed(m, pn);
+ warn("Opened for deep reflection: " + m.getName() + "/" + pn);
}
+
private static void addExtraExportsOrOpens(Layer bootLayer,
Map<String, List<String>> map,
boolean opens)
{
for (Map.Entry<String, List<String>> e : map.entrySet()) {
// the key is $MODULE/$PACKAGE
String key = e.getKey();
String[] s = key.split("/");
if (s.length != 2)
! fail("Unable to parse as <module>/<package>: " + key);
String mn = s[0];
String pn = s[1];
if (mn.isEmpty() || pn.isEmpty())
! fail("Module and package name must be specified: " + key);
// The exporting module is in the boot layer
Module m;
Optional<Module> om = bootLayer.findModule(mn);
if (!om.isPresent()) {
*** 583,602 ****
while (value != null) {
int pos = value.indexOf('=');
if (pos == -1)
! fail("Unable to parse: " + value);
if (pos == 0)
fail("Missing module name in: " + value);
// key is <module> or <module>/<package>
String key = value.substring(0, pos);
String rhs = value.substring(pos+1);
if (rhs.isEmpty())
! fail("Unable to parse: " + value);
// value is <module>(,<module>)* or <file>(<pathsep><file>)*
if (!allowDuplicates && map.containsKey(key))
fail(key + " specified more than once");
List<String> values = map.computeIfAbsent(key, k -> new ArrayList<>());
--- 637,656 ----
while (value != null) {
int pos = value.indexOf('=');
if (pos == -1)
! fail("Unable to parse as <module>=<value>: " + value);
if (pos == 0)
fail("Missing module name in: " + value);
// key is <module> or <module>/<package>
String key = value.substring(0, pos);
String rhs = value.substring(pos+1);
if (rhs.isEmpty())
! fail("Unable to parse as <module>=<value>: " + value);
// value is <module>(,<module>)* or <file>(<pathsep><file>)*
if (!allowDuplicates && map.containsKey(key))
fail(key + " specified more than once");
List<String> values = map.computeIfAbsent(key, k -> new ArrayList<>());
*** 625,634 ****
--- 679,715 ----
private static String getAndRemoveProperty(String key) {
return (String)System.getProperties().remove(key);
}
/**
+ * Checks the names and resolution bit of each module in the configuration,
+ * emitting warnings if needed.
+ */
+ private static void checkModuleNamesAndStatus(Configuration cf) {
+ String incubating = null;
+ for (ResolvedModule rm : cf.modules()) {
+ ModuleReference mref = rm.reference();
+ String mn = mref.descriptor().name();
+
+ // emit warning if module name ends with a non-Java letter
+ //if (!Checks.hasLegalModuleNameLastCharacter(mn))
+ // warn("Module name \"" + mn + "\" may soon be illegal");
+
+ // emit warning if the WARN_INCUBATING module resolution bit set
+ if (ModuleResolution.hasIncubatingWarning(mref)) {
+ if (incubating == null) {
+ incubating = mn;
+ } else {
+ incubating += ", " + mn;
+ }
+ }
+ }
+ if (incubating != null)
+ warn("using incubating module(s): " + incubating);
+ }
+
+ /**
* Throws a RuntimeException with the given message
*/
static void fail(String m) {
throw new RuntimeException(m);
}
< prev index next >