8237484: Improve module system bootstrap

Reviewed-by: alanb
This commit is contained in:
Claes Redestad 2020-02-07 10:23:35 +01:00
parent 9c8f05279c
commit 38f0c08ee0
2 changed files with 75 additions and 62 deletions

View file

@ -132,7 +132,7 @@ public final class Module implements AnnotatedElement {
Version version = descriptor.version().orElse(null);
String vs = Objects.toString(version, null);
String loc = Objects.toString(uri, null);
String[] packages = descriptor.packages().toArray(new String[0]);
Object[] packages = descriptor.packages().toArray();
defineModule0(this, isOpen, vs, loc, packages);
}
@ -1075,35 +1075,49 @@ public final class Module implements AnnotatedElement {
{
boolean isBootLayer = (ModuleLayer.boot() == null);
int cap = (int)(cf.modules().size() / 0.75f + 1.0f);
int numModules = cf.modules().size();
int cap = (int)(numModules / 0.75f + 1.0f);
Map<String, Module> nameToModule = new HashMap<>(cap);
Map<String, ClassLoader> nameToLoader = new HashMap<>(cap);
Set<ClassLoader> loaders = new HashSet<>();
// to avoid repeated lookups and reduce iteration overhead, we create
// arrays holding correlated information about each module.
ResolvedModule[] resolvedModules = new ResolvedModule[numModules];
Module[] modules = new Module[numModules];
ClassLoader[] classLoaders = new ClassLoader[numModules];
resolvedModules = cf.modules().toArray(resolvedModules);
// record that we want to bind the layer to non-boot and non-platform
// module loaders as a final step
HashSet<ClassLoader> toBindLoaders = new HashSet<>(4);
boolean hasPlatformModules = false;
// map each module to a class loader
for (ResolvedModule resolvedModule : cf.modules()) {
String name = resolvedModule.name();
ClassLoader pcl = ClassLoaders.platformClassLoader();
for (int index = 0; index < numModules; index++) {
String name = resolvedModules[index].name();
ClassLoader loader = clf.apply(name);
nameToLoader.put(name, loader);
if (loader == null || loader == ClassLoaders.platformClassLoader()) {
if (loader == null || loader == pcl) {
if (!(clf instanceof ModuleLoaderMap.Mapper)) {
throw new IllegalArgumentException("loader can't be 'null'"
+ " or the platform class loader");
}
hasPlatformModules = true;
} else {
loaders.add(loader);
toBindLoaders.add(loader);
}
classLoaders[index] = loader;
}
// define each module in the configuration to the VM
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
for (int index = 0; index < numModules; index++) {
ModuleReference mref = resolvedModules[index].reference();
ModuleDescriptor descriptor = mref.descriptor();
String name = descriptor.name();
ClassLoader loader = nameToLoader.get(name);
ClassLoader loader = classLoaders[index];
Module m;
if (loader == null && name.equals("java.base")) {
// java.base is already defined to the VM
@ -1113,16 +1127,15 @@ public final class Module implements AnnotatedElement {
m = new Module(layer, loader, descriptor, uri);
}
nameToModule.put(name, m);
modules[index] = m;
}
// setup readability and exports/opens
for (ResolvedModule resolvedModule : cf.modules()) {
for (int index = 0; index < numModules; index++) {
ResolvedModule resolvedModule = resolvedModules[index];
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
String mn = descriptor.name();
Module m = nameToModule.get(mn);
assert m != null;
Module m = modules[index];
// reads
Set<Module> reads = new HashSet<>();
@ -1174,16 +1187,15 @@ public final class Module implements AnnotatedElement {
// if there are modules defined to the boot or platform class loaders
// then register the modules in the class loader's services catalog
if (hasPlatformModules) {
ClassLoader pcl = ClassLoaders.platformClassLoader();
ServicesCatalog bootCatalog = BootLoader.getServicesCatalog();
ServicesCatalog pclCatalog = ServicesCatalog.getServicesCatalog(pcl);
for (ResolvedModule resolvedModule : cf.modules()) {
for (int index = 0; index < numModules; index++) {
ResolvedModule resolvedModule = resolvedModules[index];
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
if (!descriptor.provides().isEmpty()) {
String name = descriptor.name();
Module m = nameToModule.get(name);
ClassLoader loader = nameToLoader.get(name);
Module m = modules[index];
ClassLoader loader = classLoaders[index];
if (loader == null) {
bootCatalog.register(m);
} else if (loader == pcl) {
@ -1194,7 +1206,7 @@ public final class Module implements AnnotatedElement {
}
// record that there is a layer with modules defined to the class loader
for (ClassLoader loader : loaders) {
for (ClassLoader loader : toBindLoaders) {
layer.bindToLoader(loader);
}
@ -1623,7 +1635,7 @@ public final class Module implements AnnotatedElement {
boolean isOpen,
String version,
String location,
String[] pns);
Object[] pns);
// JVM_AddReadsModule
private static native void addReads0(Module from, Module to);

View file

@ -140,9 +140,9 @@ public final class ModuleBootstrap {
*/
public static ModuleLayer boot() throws Exception {
// Step 0: Command line options
Counters.start();
long t0 = System.nanoTime();
// Step 0: Command line options
ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
ModuleFinder appModulePath = finderFor("jdk.module.path");
@ -157,6 +157,7 @@ public final class ModuleBootstrap {
if (trace != null && Boolean.parseBoolean(trace))
traceOutput = System.out;
Counters.add("jdk.module.boot.0.commandLineTime");
// Step 1: The observable system modules, either all system modules
// or the system modules pre-generated for the initial module (the
@ -164,8 +165,6 @@ public final class ModuleBootstrap {
// are pre-generated for the initial module then resolution can be
// skipped.
long t1 = System.nanoTime();
SystemModules systemModules = null;
ModuleFinder systemModuleFinder;
@ -215,16 +214,13 @@ public final class ModuleBootstrap {
archivedModuleGraph = null;
}
Counters.add("jdk.module.boot.1.systemModulesTime", t1);
Counters.add("jdk.module.boot.1.systemModulesTime");
// Step 2: Define and load java.base. This patches all classes loaded
// to date so that they are members of java.base. Once java.base is
// loaded then resources in java.base are available for error messages
// needed from here on.
long t2 = System.nanoTime();
ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
if (base == null)
throw new InternalError(JAVA_BASE + " not found");
@ -234,9 +230,6 @@ public final class ModuleBootstrap {
BootLoader.loadModule(base);
Modules.defineModule(null, base.descriptor(), baseUri);
Counters.add("jdk.module.boot.2.defineBaseTime", t2);
// Step 2a: Scan all modules when --validate-modules specified
if (getAndRemoveProperty("jdk.module.validation") != null) {
@ -246,12 +239,11 @@ public final class ModuleBootstrap {
}
}
Counters.add("jdk.module.boot.2.defineBaseTime");
// Step 3: If resolution is needed then create the module finder and
// the set of root modules to resolve.
long t3 = System.nanoTime();
ModuleFinder savedModuleFinder = null;
ModuleFinder finder;
Set<String> roots;
@ -341,15 +333,13 @@ public final class ModuleBootstrap {
roots = null;
}
Counters.add("jdk.module.boot.3.optionsAndRootsTime", t3);
Counters.add("jdk.module.boot.3.optionsAndRootsTime");
// Step 4: Resolve the root modules, with service binding, to create
// the configuration for the boot layer. If resolution is not needed
// then create the configuration for the boot layer from the
// readability graph created at link time.
long t4 = System.nanoTime();
Configuration cf;
if (needResolution) {
cf = Modules.newBootLayerConfiguration(finder, roots, traceOutput);
@ -370,8 +360,7 @@ public final class ModuleBootstrap {
.forEach(mn -> warnUnknownModule(PATCH_MODULE, mn));
}
Counters.add("jdk.module.boot.4.resolveTime", t4);
Counters.add("jdk.module.boot.4.resolveTime");
// Step 5: Map the modules in the configuration to class loaders.
// The static configuration provides the mapping of standard and JDK
@ -380,8 +369,6 @@ public final class ModuleBootstrap {
// application module path) are defined to the application class
// loader.
long t5 = System.nanoTime();
// mapping of modules to class loaders
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
@ -409,16 +396,12 @@ public final class ModuleBootstrap {
// load/register the modules with the built-in class loaders
loadModules(cf, clf);
Counters.add("jdk.module.boot.5.loadModulesTime", t5);
Counters.add("jdk.module.boot.5.loadModulesTime");
// Step 6: Define all modules to the VM
long t6 = System.nanoTime();
ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
Counters.add("jdk.module.boot.6.layerCreateTime", t6);
Counters.add("jdk.module.boot.6.layerCreateTime");
// Step 7: Miscellaneous
@ -428,7 +411,6 @@ public final class ModuleBootstrap {
}
// --add-reads, --add-exports/--add-opens, and --illegal-access
long t7 = System.nanoTime();
addExtraReads(bootLayer);
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
@ -446,7 +428,7 @@ public final class ModuleBootstrap {
exportedPackagesToOpen,
bootLayer,
extraExportsOrOpens);
Counters.add("jdk.module.boot.7.adjustModulesTime", t7);
Counters.add("jdk.module.boot.7.adjustModulesTime");
// save module finders for later use
if (savedModuleFinder != null) {
@ -468,8 +450,7 @@ public final class ModuleBootstrap {
}
// total time to initialize
Counters.add("jdk.module.boot.totalTime", t0);
Counters.publish();
Counters.publish("jdk.module.boot.totalTime");
return bootLayer;
}
@ -1030,6 +1011,9 @@ public final class ModuleBootstrap {
private static final boolean PUBLISH_COUNTERS;
private static final boolean PRINT_COUNTERS;
private static Map<String, Long> counters;
private static long startTime;
private static long previousTime;
static {
String s = System.getProperty("jdk.module.boot.usePerfData");
if (s == null) {
@ -1043,27 +1027,44 @@ public final class ModuleBootstrap {
}
/**
* Add a counter
* Start counting time.
*/
static void add(String name, long start) {
if (PUBLISH_COUNTERS || PRINT_COUNTERS) {
counters.put(name, (System.nanoTime() - start));
static void start() {
if (PUBLISH_COUNTERS) {
startTime = previousTime = System.nanoTime();
}
}
/**
* Add a counter - storing the time difference between now and the
* previous add or the start.
*/
static void add(String name) {
if (PUBLISH_COUNTERS) {
long current = System.nanoTime();
long elapsed = current - previousTime;
previousTime = current;
counters.put(name, elapsed);
}
}
/**
* Publish the counters to the instrumentation buffer or stdout.
*/
static void publish() {
if (PUBLISH_COUNTERS || PRINT_COUNTERS) {
static void publish(String totalTimeName) {
if (PUBLISH_COUNTERS) {
long currentTime = System.nanoTime();
for (Map.Entry<String, Long> e : counters.entrySet()) {
String name = e.getKey();
long value = e.getValue();
if (PUBLISH_COUNTERS)
PerfCounter.newPerfCounter(name).set(value);
if (PRINT_COUNTERS)
System.out.println(name + " = " + value);
}
long elapsedTotal = currentTime - startTime;
PerfCounter.newPerfCounter(totalTimeName).set(elapsedTotal);
if (PRINT_COUNTERS)
System.out.println(totalTimeName + " = " + elapsedTotal);
}
}
}