mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +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);
|
Version version = descriptor.version().orElse(null);
|
||||||
String vs = Objects.toString(version, null);
|
String vs = Objects.toString(version, null);
|
||||||
String loc = Objects.toString(uri, 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);
|
defineModule0(this, isOpen, vs, loc, packages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1075,35 +1075,49 @@ public final class Module implements AnnotatedElement {
|
||||||
{
|
{
|
||||||
boolean isBootLayer = (ModuleLayer.boot() == null);
|
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, 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;
|
boolean hasPlatformModules = false;
|
||||||
|
|
||||||
// map each module to a class loader
|
// map each module to a class loader
|
||||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
ClassLoader pcl = ClassLoaders.platformClassLoader();
|
||||||
String name = resolvedModule.name();
|
|
||||||
|
for (int index = 0; index < numModules; index++) {
|
||||||
|
String name = resolvedModules[index].name();
|
||||||
ClassLoader loader = clf.apply(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)) {
|
if (!(clf instanceof ModuleLoaderMap.Mapper)) {
|
||||||
throw new IllegalArgumentException("loader can't be 'null'"
|
throw new IllegalArgumentException("loader can't be 'null'"
|
||||||
+ " or the platform class loader");
|
+ " or the platform class loader");
|
||||||
}
|
}
|
||||||
hasPlatformModules = true;
|
hasPlatformModules = true;
|
||||||
} else {
|
} else {
|
||||||
loaders.add(loader);
|
toBindLoaders.add(loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
classLoaders[index] = loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
// define each module in the configuration to the VM
|
// define each module in the configuration to the VM
|
||||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
for (int index = 0; index < numModules; index++) {
|
||||||
ModuleReference mref = resolvedModule.reference();
|
ModuleReference mref = resolvedModules[index].reference();
|
||||||
ModuleDescriptor descriptor = mref.descriptor();
|
ModuleDescriptor descriptor = mref.descriptor();
|
||||||
String name = descriptor.name();
|
String name = descriptor.name();
|
||||||
ClassLoader loader = nameToLoader.get(name);
|
ClassLoader loader = classLoaders[index];
|
||||||
Module m;
|
Module m;
|
||||||
if (loader == null && name.equals("java.base")) {
|
if (loader == null && name.equals("java.base")) {
|
||||||
// java.base is already defined to the VM
|
// 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);
|
m = new Module(layer, loader, descriptor, uri);
|
||||||
}
|
}
|
||||||
nameToModule.put(name, m);
|
nameToModule.put(name, m);
|
||||||
|
modules[index] = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup readability and exports/opens
|
// 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();
|
ModuleReference mref = resolvedModule.reference();
|
||||||
ModuleDescriptor descriptor = mref.descriptor();
|
ModuleDescriptor descriptor = mref.descriptor();
|
||||||
|
Module m = modules[index];
|
||||||
String mn = descriptor.name();
|
|
||||||
Module m = nameToModule.get(mn);
|
|
||||||
assert m != null;
|
|
||||||
|
|
||||||
// reads
|
// reads
|
||||||
Set<Module> reads = new HashSet<>();
|
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
|
// if there are modules defined to the boot or platform class loaders
|
||||||
// then register the modules in the class loader's services catalog
|
// then register the modules in the class loader's services catalog
|
||||||
if (hasPlatformModules) {
|
if (hasPlatformModules) {
|
||||||
ClassLoader pcl = ClassLoaders.platformClassLoader();
|
|
||||||
ServicesCatalog bootCatalog = BootLoader.getServicesCatalog();
|
ServicesCatalog bootCatalog = BootLoader.getServicesCatalog();
|
||||||
ServicesCatalog pclCatalog = ServicesCatalog.getServicesCatalog(pcl);
|
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();
|
ModuleReference mref = resolvedModule.reference();
|
||||||
ModuleDescriptor descriptor = mref.descriptor();
|
ModuleDescriptor descriptor = mref.descriptor();
|
||||||
if (!descriptor.provides().isEmpty()) {
|
if (!descriptor.provides().isEmpty()) {
|
||||||
String name = descriptor.name();
|
Module m = modules[index];
|
||||||
Module m = nameToModule.get(name);
|
ClassLoader loader = classLoaders[index];
|
||||||
ClassLoader loader = nameToLoader.get(name);
|
|
||||||
if (loader == null) {
|
if (loader == null) {
|
||||||
bootCatalog.register(m);
|
bootCatalog.register(m);
|
||||||
} else if (loader == pcl) {
|
} 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
|
// record that there is a layer with modules defined to the class loader
|
||||||
for (ClassLoader loader : loaders) {
|
for (ClassLoader loader : toBindLoaders) {
|
||||||
layer.bindToLoader(loader);
|
layer.bindToLoader(loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1623,7 +1635,7 @@ public final class Module implements AnnotatedElement {
|
||||||
boolean isOpen,
|
boolean isOpen,
|
||||||
String version,
|
String version,
|
||||||
String location,
|
String location,
|
||||||
String[] pns);
|
Object[] pns);
|
||||||
|
|
||||||
// JVM_AddReadsModule
|
// JVM_AddReadsModule
|
||||||
private static native void addReads0(Module from, Module to);
|
private static native void addReads0(Module from, Module to);
|
||||||
|
|
|
@ -140,9 +140,9 @@ public final class ModuleBootstrap {
|
||||||
*/
|
*/
|
||||||
public static ModuleLayer boot() throws Exception {
|
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 upgradeModulePath = finderFor("jdk.module.upgrade.path");
|
||||||
ModuleFinder appModulePath = finderFor("jdk.module.path");
|
ModuleFinder appModulePath = finderFor("jdk.module.path");
|
||||||
|
@ -157,6 +157,7 @@ public final class ModuleBootstrap {
|
||||||
if (trace != null && Boolean.parseBoolean(trace))
|
if (trace != null && Boolean.parseBoolean(trace))
|
||||||
traceOutput = System.out;
|
traceOutput = System.out;
|
||||||
|
|
||||||
|
Counters.add("jdk.module.boot.0.commandLineTime");
|
||||||
|
|
||||||
// Step 1: The observable system modules, either all system modules
|
// Step 1: The observable system modules, either all system modules
|
||||||
// or the system modules pre-generated for the initial module (the
|
// 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
|
// are pre-generated for the initial module then resolution can be
|
||||||
// skipped.
|
// skipped.
|
||||||
|
|
||||||
long t1 = System.nanoTime();
|
|
||||||
|
|
||||||
SystemModules systemModules = null;
|
SystemModules systemModules = null;
|
||||||
ModuleFinder systemModuleFinder;
|
ModuleFinder systemModuleFinder;
|
||||||
|
|
||||||
|
@ -215,16 +214,13 @@ public final class ModuleBootstrap {
|
||||||
archivedModuleGraph = null;
|
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
|
// 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
|
// 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
|
// loaded then resources in java.base are available for error messages
|
||||||
// needed from here on.
|
// needed from here on.
|
||||||
|
|
||||||
long t2 = System.nanoTime();
|
|
||||||
|
|
||||||
ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
|
ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
|
||||||
if (base == null)
|
if (base == null)
|
||||||
throw new InternalError(JAVA_BASE + " not found");
|
throw new InternalError(JAVA_BASE + " not found");
|
||||||
|
@ -234,9 +230,6 @@ public final class ModuleBootstrap {
|
||||||
BootLoader.loadModule(base);
|
BootLoader.loadModule(base);
|
||||||
Modules.defineModule(null, base.descriptor(), baseUri);
|
Modules.defineModule(null, base.descriptor(), baseUri);
|
||||||
|
|
||||||
Counters.add("jdk.module.boot.2.defineBaseTime", t2);
|
|
||||||
|
|
||||||
|
|
||||||
// Step 2a: Scan all modules when --validate-modules specified
|
// Step 2a: Scan all modules when --validate-modules specified
|
||||||
|
|
||||||
if (getAndRemoveProperty("jdk.module.validation") != null) {
|
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
|
// Step 3: If resolution is needed then create the module finder and
|
||||||
// the set of root modules to resolve.
|
// the set of root modules to resolve.
|
||||||
|
|
||||||
long t3 = System.nanoTime();
|
|
||||||
|
|
||||||
ModuleFinder savedModuleFinder = null;
|
ModuleFinder savedModuleFinder = null;
|
||||||
ModuleFinder finder;
|
ModuleFinder finder;
|
||||||
Set<String> roots;
|
Set<String> roots;
|
||||||
|
@ -341,15 +333,13 @@ public final class ModuleBootstrap {
|
||||||
roots = null;
|
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
|
// Step 4: Resolve the root modules, with service binding, to create
|
||||||
// the configuration for the boot layer. If resolution is not needed
|
// the configuration for the boot layer. If resolution is not needed
|
||||||
// then create the configuration for the boot layer from the
|
// then create the configuration for the boot layer from the
|
||||||
// readability graph created at link time.
|
// readability graph created at link time.
|
||||||
|
|
||||||
long t4 = System.nanoTime();
|
|
||||||
|
|
||||||
Configuration cf;
|
Configuration cf;
|
||||||
if (needResolution) {
|
if (needResolution) {
|
||||||
cf = Modules.newBootLayerConfiguration(finder, roots, traceOutput);
|
cf = Modules.newBootLayerConfiguration(finder, roots, traceOutput);
|
||||||
|
@ -370,8 +360,7 @@ public final class ModuleBootstrap {
|
||||||
.forEach(mn -> warnUnknownModule(PATCH_MODULE, mn));
|
.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.
|
// Step 5: Map the modules in the configuration to class loaders.
|
||||||
// The static configuration provides the mapping of standard and JDK
|
// 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
|
// application module path) are defined to the application class
|
||||||
// loader.
|
// loader.
|
||||||
|
|
||||||
long t5 = System.nanoTime();
|
|
||||||
|
|
||||||
// mapping of modules to class loaders
|
// mapping of modules to class loaders
|
||||||
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
|
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
|
// load/register the modules with the built-in class loaders
|
||||||
loadModules(cf, clf);
|
loadModules(cf, clf);
|
||||||
|
Counters.add("jdk.module.boot.5.loadModulesTime");
|
||||||
Counters.add("jdk.module.boot.5.loadModulesTime", t5);
|
|
||||||
|
|
||||||
|
|
||||||
// Step 6: Define all modules to the VM
|
// Step 6: Define all modules to the VM
|
||||||
|
|
||||||
long t6 = System.nanoTime();
|
|
||||||
ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
|
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
|
// Step 7: Miscellaneous
|
||||||
|
|
||||||
|
@ -428,7 +411,6 @@ public final class ModuleBootstrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
// --add-reads, --add-exports/--add-opens, and --illegal-access
|
// --add-reads, --add-exports/--add-opens, and --illegal-access
|
||||||
long t7 = System.nanoTime();
|
|
||||||
addExtraReads(bootLayer);
|
addExtraReads(bootLayer);
|
||||||
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
|
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
|
||||||
|
|
||||||
|
@ -446,7 +428,7 @@ public final class ModuleBootstrap {
|
||||||
exportedPackagesToOpen,
|
exportedPackagesToOpen,
|
||||||
bootLayer,
|
bootLayer,
|
||||||
extraExportsOrOpens);
|
extraExportsOrOpens);
|
||||||
Counters.add("jdk.module.boot.7.adjustModulesTime", t7);
|
Counters.add("jdk.module.boot.7.adjustModulesTime");
|
||||||
|
|
||||||
// save module finders for later use
|
// save module finders for later use
|
||||||
if (savedModuleFinder != null) {
|
if (savedModuleFinder != null) {
|
||||||
|
@ -468,8 +450,7 @@ public final class ModuleBootstrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
// total time to initialize
|
// total time to initialize
|
||||||
Counters.add("jdk.module.boot.totalTime", t0);
|
Counters.publish("jdk.module.boot.totalTime");
|
||||||
Counters.publish();
|
|
||||||
|
|
||||||
return bootLayer;
|
return bootLayer;
|
||||||
}
|
}
|
||||||
|
@ -1030,6 +1011,9 @@ public final class ModuleBootstrap {
|
||||||
private static final boolean PUBLISH_COUNTERS;
|
private static final boolean PUBLISH_COUNTERS;
|
||||||
private static final boolean PRINT_COUNTERS;
|
private static final boolean PRINT_COUNTERS;
|
||||||
private static Map<String, Long> counters;
|
private static Map<String, Long> counters;
|
||||||
|
private static long startTime;
|
||||||
|
private static long previousTime;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String s = System.getProperty("jdk.module.boot.usePerfData");
|
String s = System.getProperty("jdk.module.boot.usePerfData");
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
|
@ -1043,27 +1027,44 @@ public final class ModuleBootstrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a counter
|
* Start counting time.
|
||||||
*/
|
*/
|
||||||
static void add(String name, long start) {
|
static void start() {
|
||||||
if (PUBLISH_COUNTERS || PRINT_COUNTERS) {
|
if (PUBLISH_COUNTERS) {
|
||||||
counters.put(name, (System.nanoTime() - start));
|
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.
|
* Publish the counters to the instrumentation buffer or stdout.
|
||||||
*/
|
*/
|
||||||
static void publish() {
|
static void publish(String totalTimeName) {
|
||||||
if (PUBLISH_COUNTERS || PRINT_COUNTERS) {
|
if (PUBLISH_COUNTERS) {
|
||||||
|
long currentTime = System.nanoTime();
|
||||||
for (Map.Entry<String, Long> e : counters.entrySet()) {
|
for (Map.Entry<String, Long> e : counters.entrySet()) {
|
||||||
String name = e.getKey();
|
String name = e.getKey();
|
||||||
long value = e.getValue();
|
long value = e.getValue();
|
||||||
if (PUBLISH_COUNTERS)
|
PerfCounter.newPerfCounter(name).set(value);
|
||||||
PerfCounter.newPerfCounter(name).set(value);
|
|
||||||
if (PRINT_COUNTERS)
|
if (PRINT_COUNTERS)
|
||||||
System.out.println(name + " = " + value);
|
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