Skip to content
Permalink
Browse files

8237878: Improve ModuleLoaderMap datastructures

Reviewed-by: alanb, forax
  • Loading branch information
cl4es committed Feb 10, 2020
1 parent c23d1de commit 326a939e1bed5e5c297c28d2841b1f0a4ab2e649
@@ -1094,13 +1094,14 @@ public boolean canUse(Class<?> service) {

// map each module to a class loader
ClassLoader pcl = ClassLoaders.platformClassLoader();
boolean isModuleLoaderMapper = ModuleLoaderMap.isBuiltinMapper(clf);

for (int index = 0; index < numModules; index++) {
String name = resolvedModules[index].name();
ClassLoader loader = clf.apply(name);

if (loader == null || loader == pcl) {
if (!(clf instanceof ModuleLoaderMap.Mapper)) {
if (!isModuleLoaderMapper) {
throw new IllegalArgumentException("loader can't be 'null'"
+ " or the platform class loader");
}
@@ -79,7 +79,7 @@ public ModuleReference reference() {
* @return The module descriptor
*/
ModuleDescriptor descriptor() {
return reference().descriptor();
return mref.descriptor();
}

/**
@@ -93,7 +93,7 @@ ModuleDescriptor descriptor() {
* @return The module name
*/
public String name() {
return reference().descriptor().name();
return mref.descriptor().name();
}

/**
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,8 @@
import java.lang.module.Configuration;
import java.lang.module.ModuleFinder;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

import jdk.internal.misc.VM;

@@ -39,26 +39,26 @@
final class ArchivedModuleGraph {
private static ArchivedModuleGraph archivedModuleGraph;

private final String mainModule;
private final boolean hasSplitPackages;
private final boolean hasIncubatorModules;
private final ModuleFinder finder;
private final Configuration configuration;
private final Function<String, ClassLoader> classLoaderFunction;
private final Map<String, Set<String>> concealedPackagesToOpen;
private final Map<String, Set<String>> exportedPackagesToOpen;

private ArchivedModuleGraph(String mainModule,
boolean hasSplitPackages,
boolean hasIncubatorModules,
ModuleFinder finder,
Configuration configuration,
Map<String, Set<String>> concealedPackagesToOpen,
Map<String, Set<String>> exportedPackagesToOpen) {
this.mainModule = mainModule;
public ArchivedModuleGraph(boolean hasSplitPackages,
boolean hasIncubatorModules,
ModuleFinder finder,
Configuration configuration,
Function<String, ClassLoader> classLoaderFunction,
Map<String, Set<String>> concealedPackagesToOpen,
Map<String, Set<String>> exportedPackagesToOpen) {
this.hasSplitPackages = hasSplitPackages;
this.hasIncubatorModules = hasIncubatorModules;
this.finder = finder;
this.configuration = configuration;
this.classLoaderFunction = classLoaderFunction;
this.concealedPackagesToOpen = concealedPackagesToOpen;
this.exportedPackagesToOpen = exportedPackagesToOpen;
}
@@ -71,6 +71,10 @@ Configuration configuration() {
return configuration;
}

Function<String, ClassLoader> classLoaderFunction() {
return classLoaderFunction;
}

Map<String, Set<String>> concealedPackagesToOpen() {
return concealedPackagesToOpen;
}
@@ -92,7 +96,8 @@ boolean hasIncubatorModules() {
*/
static ArchivedModuleGraph get(String mainModule) {
ArchivedModuleGraph graph = archivedModuleGraph;
if (graph != null && Objects.equals(mainModule, graph.mainModule)) {
// We only allow the unnamed module (default) case for now
if (mainModule == null) {
return graph;
} else {
return null;
@@ -102,23 +107,8 @@ static ArchivedModuleGraph get(String mainModule) {
/**
* Archive the module graph for the given initial module.
*/
static void archive(String mainModule,
boolean hasSplitPackages,
boolean hasIncubatorModules,
ModuleFinder finder,
Configuration configuration,
Map<String, Set<String>> concealedPackagesToOpen,
Map<String, Set<String>> exportedPackagesToOpen) {
if (mainModule != null) {
throw new UnsupportedOperationException();
}
archivedModuleGraph = new ArchivedModuleGraph(mainModule,
hasSplitPackages,
hasIncubatorModules,
finder,
configuration,
concealedPackagesToOpen,
exportedPackagesToOpen);
static void archive(ArchivedModuleGraph graph) {
archivedModuleGraph = graph;
}

static {
@@ -370,7 +370,12 @@ public static ModuleLayer boot() throws Exception {
// loader.

// mapping of modules to class loaders
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
Function<String, ClassLoader> clf;
if (archivedModuleGraph != null) {
clf = archivedModuleGraph.classLoaderFunction();
} else {
clf = ModuleLoaderMap.mappingFunction(cf);
}

// check that all modules to be mapped to the boot loader will be
// loaded from the runtime image
@@ -440,13 +445,14 @@ public static ModuleLayer boot() throws Exception {
// Module graph can be archived at CDS dump time. Only allow the
// unnamed module case for now.
if (canArchive && (mainModule == null)) {
ArchivedModuleGraph.archive(mainModule,
hasSplitPackages,
hasIncubatorModules,
systemModuleFinder,
cf,
concealedPackagesToOpen,
exportedPackagesToOpen);
ArchivedModuleGraph.archive(
new ArchivedModuleGraph(hasSplitPackages,
hasIncubatorModules,
systemModuleFinder,
cf,
clf,
concealedPackagesToOpen,
exportedPackagesToOpen));
}

// total time to initialize
@@ -737,7 +743,6 @@ private static void addExtraExportsOrOpens(ModuleLayer bootLayer,
Modules.addExports(m, pn, other);
}
}

}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,14 +28,12 @@
import java.lang.module.Configuration;
import java.lang.module.ResolvedModule;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import jdk.internal.loader.ClassLoaders;


/**
* Supports the mapping of modules to class loaders. The set of modules mapped
* to the boot and platform class loaders is generated at build time from
@@ -46,67 +44,96 @@
/**
* Maps the system modules to the built-in class loaders.
*/
public static final class Mapper implements Function<String, ClassLoader> {
private final Map<String, ClassLoader> map;
private static final class Mapper implements Function<String, ClassLoader> {

private static final ClassLoader PLATFORM_CLASSLOADER =
ClassLoaders.platformClassLoader();
private static final ClassLoader APP_CLASSLOADER =
ClassLoaders.appClassLoader();

private static final Integer PLATFORM_LOADER_INDEX = 1;
private static final Integer APP_LOADER_INDEX = 2;

Mapper(Map<String, ClassLoader> map) {
this.map = map; // defensive copy not needed
/**
* Map from module to a class loader index. The index is resolved to the
* actual class loader in {@code apply}.
*/
private final Map<String, Integer> map;

/**
* Creates a Mapper to map module names in the given Configuration to
* built-in classloaders.
*
* As a proxy for the actual classloader, we store an easily archiveable
* index value in the internal map. The index is stored as a boxed value
* so that we can cheaply do identity comparisons during bootstrap.
*/
Mapper(Configuration cf) {
var map = new HashMap<String, Integer>();
for (ResolvedModule resolvedModule : cf.modules()) {
String mn = resolvedModule.name();
if (!Modules.bootModules.contains(mn)) {
if (Modules.platformModules.contains(mn)) {
map.put(mn, PLATFORM_LOADER_INDEX);
} else {
map.put(mn, APP_LOADER_INDEX);
}
}
}
this.map = map;
}

@Override
public ClassLoader apply(String name) {
return map.get(name);
Integer loader = map.get(name);
if (loader == APP_LOADER_INDEX) {
return APP_CLASSLOADER;
} else if (loader == PLATFORM_LOADER_INDEX) {
return PLATFORM_CLASSLOADER;
} else { // BOOT_LOADER_INDEX
return null;
}
}
}

/**
* Returns the names of the modules defined to the boot loader.
*/
public static Set<String> bootModules() {
// The list of boot modules generated at build time.
String[] BOOT_MODULES = new String[] { "@@BOOT_MODULE_NAMES@@" };
Set<String> bootModules = new HashSet<>(BOOT_MODULES.length);
for (String mn : BOOT_MODULES) {
bootModules.add(mn);
}
return bootModules;
return Modules.bootModules;
}

/**
* Returns the names of the modules defined to the platform loader.
*/
public static Set<String> platformModules() {
// The list of platform modules generated at build time.
String[] PLATFORM_MODULES = new String[] { "@@PLATFORM_MODULE_NAMES@@" };
Set<String> platformModules = new HashSet<>(PLATFORM_MODULES.length);
for (String mn : PLATFORM_MODULES) {
platformModules.add(mn);
}
return platformModules;
return Modules.platformModules;
}

private static class Modules {
// list of boot modules is generated at build time.
private static final Set<String> bootModules =
Set.of(new String[] { "@@BOOT_MODULE_NAMES@@" });

// list of platform modules is generated at build time.
private static final Set<String> platformModules =
Set.of(new String[] { "@@PLATFORM_MODULE_NAMES@@" });
}

/**
* Returns the function to map modules in the given configuration to the
* Returns a function to map modules in the given configuration to the
* built-in class loaders.
*/
static Function<String, ClassLoader> mappingFunction(Configuration cf) {
Set<String> bootModules = bootModules();
Set<String> platformModules = platformModules();

ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
ClassLoader appClassLoader = ClassLoaders.appClassLoader();

Map<String, ClassLoader> map = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
String mn = resolvedModule.name();
if (!bootModules.contains(mn)) {
if (platformModules.contains(mn)) {
map.put(mn, platformClassLoader);
} else {
map.put(mn, appClassLoader);
}
}
}
return new Mapper(map);
return new Mapper(cf);
}

/**
* When defining modules for a configuration, we only allow defining modules
* to the boot or platform classloader if the ClassLoader mapping function
* originate from here.
*/
public static boolean isBuiltinMapper(Function<String, ClassLoader> clf) {
return clf instanceof Mapper;
}
}

0 comments on commit 326a939

Please sign in to comment.