mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8237484: Improve module system bootstrap
Reviewed-by: alanb
This commit is contained in:
parent
9c8f05279c
commit
38f0c08ee0
2 changed files with 75 additions and 62 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue