Skip to content

Commit

Permalink
8237484: Improve module system bootstrap
Browse files Browse the repository at this point in the history
Reviewed-by: alanb
  • Loading branch information
cl4es committed Feb 7, 2020
1 parent 9c8f052 commit 38f0c08
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 62 deletions.
60 changes: 36 additions & 24 deletions src/java.base/share/classes/java/lang/Module.java
Expand Up @@ -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);
}

Expand Down Expand Up @@ -1075,35 +1075,49 @@ static Map<String, Module> defineModules(Configuration cf,
{
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
Expand All @@ -1113,16 +1127,15 @@ static Map<String, Module> defineModules(Configuration cf,
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<>();
Expand Down Expand Up @@ -1174,16 +1187,15 @@ static Map<String, Module> defineModules(Configuration cf,
// 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) {
Expand All @@ -1194,7 +1206,7 @@ static Map<String, Module> defineModules(Configuration cf,
}

// record that there is a layer with modules defined to the class loader
for (ClassLoader loader : loaders) {
for (ClassLoader loader : toBindLoaders) {
layer.bindToLoader(loader);
}

Expand Down Expand Up @@ -1623,7 +1635,7 @@ private static native void defineModule0(Module module,
boolean isOpen,
String version,
String location,
String[] pns);
Object[] pns);

// JVM_AddReadsModule
private static native void addReads0(Module from, Module to);
Expand Down
Expand Up @@ -140,9 +140,9 @@ public static ModuleFinder limitedFinder() {
*/
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");
Expand All @@ -157,15 +157,14 @@ public static ModuleLayer boot() throws Exception {
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
// initial module may be the unnamed module). If the system modules
// are pre-generated for the initial module then resolution can be
// skipped.

long t1 = System.nanoTime();

SystemModules systemModules = null;
ModuleFinder systemModuleFinder;

Expand Down Expand Up @@ -215,16 +214,13 @@ public static ModuleLayer boot() throws Exception {
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");
Expand All @@ -234,9 +230,6 @@ public static ModuleLayer boot() throws Exception {
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) {
Expand All @@ -246,12 +239,11 @@ public static ModuleLayer boot() throws Exception {
}
}

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;
Expand Down Expand Up @@ -341,15 +333,13 @@ public static ModuleLayer boot() throws Exception {
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);
Expand All @@ -370,8 +360,7 @@ public static ModuleLayer boot() throws Exception {
.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
Expand All @@ -380,8 +369,6 @@ public static ModuleLayer boot() throws Exception {
// 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);

Expand Down Expand Up @@ -409,16 +396,12 @@ public static ModuleLayer boot() throws Exception {

// 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

Expand All @@ -428,7 +411,6 @@ public static ModuleLayer boot() throws Exception {
}

// --add-reads, --add-exports/--add-opens, and --illegal-access
long t7 = System.nanoTime();
addExtraReads(bootLayer);
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);

Expand All @@ -446,7 +428,7 @@ public static ModuleLayer boot() throws Exception {
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) {
Expand All @@ -468,8 +450,7 @@ public static ModuleLayer boot() throws Exception {
}

// total time to initialize
Counters.add("jdk.module.boot.totalTime", t0);
Counters.publish();
Counters.publish("jdk.module.boot.totalTime");

return bootLayer;
}
Expand Down Expand Up @@ -1030,6 +1011,9 @@ static class Counters {
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) {
Expand All @@ -1043,27 +1027,44 @@ static class Counters {
}

/**
* Add a counter
* Start counting time.
*/
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, long start) {
if (PUBLISH_COUNTERS || PRINT_COUNTERS) {
counters.put(name, (System.nanoTime() - 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);
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);
}
}
}
Expand Down

0 comments on commit 38f0c08

Please sign in to comment.