mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8244778: Archive full module graph in CDS
Reviewed-by: erikj, coleenp, lfoltan, redestad, alanb, mchung
This commit is contained in:
parent
998ce78e53
commit
03a4df0acd
59 changed files with 2052 additions and 164 deletions
|
@ -2714,6 +2714,17 @@ public abstract class ClassLoader {
|
|||
offset = unsafe.objectFieldOffset(k, name);
|
||||
return unsafe.compareAndSetReference(this, offset, null, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the VM, during -Xshare:dump
|
||||
*/
|
||||
private void resetArchivedStates() {
|
||||
parallelLockMap.clear();
|
||||
packages.clear();
|
||||
package2certs.clear();
|
||||
classes.clear();
|
||||
classLoaderValueMap = null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -55,6 +55,7 @@ import java.util.stream.Stream;
|
|||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.loader.ClassLoaders;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.module.IllegalAccessLogger;
|
||||
import jdk.internal.module.ModuleLoaderMap;
|
||||
import jdk.internal.module.ServicesCatalog;
|
||||
|
@ -246,12 +247,55 @@ public final class Module implements AnnotatedElement {
|
|||
// --
|
||||
|
||||
// special Module to mean "all unnamed modules"
|
||||
private static final Module ALL_UNNAMED_MODULE = new Module(null);
|
||||
private static final Set<Module> ALL_UNNAMED_MODULE_SET = Set.of(ALL_UNNAMED_MODULE);
|
||||
private static final Module ALL_UNNAMED_MODULE;
|
||||
private static final Set<Module> ALL_UNNAMED_MODULE_SET;
|
||||
|
||||
// special Module to mean "everyone"
|
||||
private static final Module EVERYONE_MODULE = new Module(null);
|
||||
private static final Set<Module> EVERYONE_SET = Set.of(EVERYONE_MODULE);
|
||||
private static final Module EVERYONE_MODULE;
|
||||
private static final Set<Module> EVERYONE_SET;
|
||||
|
||||
private static class ArchivedData {
|
||||
private static ArchivedData archivedData;
|
||||
private final Module allUnnamedModule;
|
||||
private final Set<Module> allUnnamedModules;
|
||||
private final Module everyoneModule;
|
||||
private final Set<Module> everyoneSet;
|
||||
|
||||
private ArchivedData() {
|
||||
this.allUnnamedModule = ALL_UNNAMED_MODULE;
|
||||
this.allUnnamedModules = ALL_UNNAMED_MODULE_SET;
|
||||
this.everyoneModule = EVERYONE_MODULE;
|
||||
this.everyoneSet = EVERYONE_SET;
|
||||
}
|
||||
|
||||
static void archive() {
|
||||
archivedData = new ArchivedData();
|
||||
}
|
||||
|
||||
static ArchivedData get() {
|
||||
return archivedData;
|
||||
}
|
||||
|
||||
static {
|
||||
VM.initializeFromArchive(ArchivedData.class);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
ArchivedData archivedData = ArchivedData.get();
|
||||
if (archivedData != null) {
|
||||
ALL_UNNAMED_MODULE = archivedData.allUnnamedModule;
|
||||
ALL_UNNAMED_MODULE_SET = archivedData.allUnnamedModules;
|
||||
EVERYONE_MODULE = archivedData.everyoneModule;
|
||||
EVERYONE_SET = archivedData.everyoneSet;
|
||||
} else {
|
||||
ALL_UNNAMED_MODULE = new Module(null);
|
||||
ALL_UNNAMED_MODULE_SET = Set.of(ALL_UNNAMED_MODULE);
|
||||
EVERYONE_MODULE = new Module(null);
|
||||
EVERYONE_SET = Set.of(EVERYONE_MODULE);
|
||||
ArchivedData.archive();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The holder of data structures to support readability, exports, and
|
||||
|
|
|
@ -2248,6 +2248,9 @@ public final class System {
|
|||
public ServicesCatalog getServicesCatalog(ModuleLayer layer) {
|
||||
return layer.getServicesCatalog();
|
||||
}
|
||||
public void bindToLoader(ModuleLayer layer, ClassLoader loader) {
|
||||
layer.bindToLoader(loader);
|
||||
}
|
||||
public Stream<ModuleLayer> layers(ModuleLayer layer) {
|
||||
return layer.layers();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
|
@ -269,4 +269,11 @@ public class SecureClassLoader extends ClassLoader {
|
|||
return cs.matchCerts(csk.cs, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the VM, during -Xshare:dump
|
||||
*/
|
||||
private void resetArchivedStates() {
|
||||
pdcache.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,6 +256,12 @@ public interface JavaLangAccess {
|
|||
*/
|
||||
ServicesCatalog getServicesCatalog(ModuleLayer layer);
|
||||
|
||||
/**
|
||||
* Record that this layer has at least one module defined to the given
|
||||
* class loader.
|
||||
*/
|
||||
void bindToLoader(ModuleLayer layer, ClassLoader loader);
|
||||
|
||||
/**
|
||||
* Returns an ordered stream of layers. The first element is the
|
||||
* given layer, the remaining elements are its parents, in DFS order.
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.loader;
|
||||
|
||||
import java.util.Map;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.module.ServicesCatalog;
|
||||
|
||||
/**
|
||||
* Used to archive the built-in class loaders, their services catalogs, and the
|
||||
* package-to-module map used by the built-in class loaders.
|
||||
*/
|
||||
class ArchivedClassLoaders {
|
||||
private static ArchivedClassLoaders archivedClassLoaders;
|
||||
|
||||
private final ClassLoader bootLoader;
|
||||
private final ClassLoader platformLoader;
|
||||
private final ClassLoader appLoader;
|
||||
private final ServicesCatalog[] servicesCatalogs;
|
||||
private final Map<String, ?> packageToModule;
|
||||
|
||||
private ArchivedClassLoaders() {
|
||||
bootLoader = ClassLoaders.bootLoader();
|
||||
platformLoader = ClassLoaders.platformClassLoader();
|
||||
appLoader = ClassLoaders.appClassLoader();
|
||||
|
||||
servicesCatalogs = new ServicesCatalog[3];
|
||||
servicesCatalogs[0] = BootLoader.getServicesCatalog();
|
||||
servicesCatalogs[1] = ServicesCatalog.getServicesCatalog(platformLoader);
|
||||
servicesCatalogs[2] = ServicesCatalog.getServicesCatalog(appLoader);
|
||||
|
||||
packageToModule = BuiltinClassLoader.packageToModule();
|
||||
}
|
||||
|
||||
ClassLoader bootLoader() {
|
||||
return bootLoader;
|
||||
}
|
||||
|
||||
ClassLoader platformLoader() {
|
||||
return platformLoader;
|
||||
}
|
||||
|
||||
ClassLoader appLoader() {
|
||||
return appLoader;
|
||||
}
|
||||
|
||||
ServicesCatalog servicesCatalog(ClassLoader loader) {
|
||||
if (loader == null) {
|
||||
return servicesCatalogs[0];
|
||||
} else if (loader == platformLoader) {
|
||||
return servicesCatalogs[1];
|
||||
} else if (loader == appLoader) {
|
||||
return servicesCatalogs[2];
|
||||
} else {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, ?> packageToModule() {
|
||||
return packageToModule;
|
||||
}
|
||||
|
||||
static void archive() {
|
||||
archivedClassLoaders = new ArchivedClassLoaders();
|
||||
}
|
||||
|
||||
static ArchivedClassLoaders get() {
|
||||
return archivedClassLoaders;
|
||||
}
|
||||
|
||||
static {
|
||||
VM.initializeFromArchive(ArchivedClassLoaders.class);
|
||||
}
|
||||
}
|
|
@ -65,7 +65,15 @@ public class BootLoader {
|
|||
}
|
||||
|
||||
// ServiceCatalog for the boot class loader
|
||||
private static final ServicesCatalog SERVICES_CATALOG = ServicesCatalog.create();
|
||||
private static final ServicesCatalog SERVICES_CATALOG;
|
||||
static {
|
||||
ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get();
|
||||
if (archivedClassLoaders != null) {
|
||||
SERVICES_CATALOG = archivedClassLoaders.servicesCatalog(null);
|
||||
} else {
|
||||
SERVICES_CATALOG = ServicesCatalog.create();
|
||||
}
|
||||
}
|
||||
|
||||
// ClassLoaderValue map for the boot class loader
|
||||
private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP
|
||||
|
|
|
@ -104,8 +104,7 @@ public class BuiltinClassLoader
|
|||
private final BuiltinClassLoader parent;
|
||||
|
||||
// the URL class path, or null if there is no class path
|
||||
private final URLClassPath ucp;
|
||||
|
||||
private @Stable URLClassPath ucp;
|
||||
|
||||
/**
|
||||
* A module defined/loaded by a built-in class loader.
|
||||
|
@ -156,10 +155,26 @@ public class BuiltinClassLoader
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// maps package name to loaded module for modules in the boot layer
|
||||
private static final Map<String, LoadedModule> packageToModule
|
||||
= new ConcurrentHashMap<>(1024);
|
||||
private static final Map<String, LoadedModule> packageToModule;
|
||||
static {
|
||||
ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get();
|
||||
if (archivedClassLoaders != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, LoadedModule> map
|
||||
= (Map<String, LoadedModule>) archivedClassLoaders.packageToModule();
|
||||
packageToModule = map;
|
||||
} else {
|
||||
packageToModule = new ConcurrentHashMap<>(1024);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked by ArchivedClassLoaders to archive the package-to-module map.
|
||||
*/
|
||||
static Map<String, ?> packageToModule() {
|
||||
return packageToModule;
|
||||
}
|
||||
|
||||
// maps a module name to a module reference
|
||||
private final Map<String, ModuleReference> nameToModule;
|
||||
|
@ -185,6 +200,21 @@ public class BuiltinClassLoader
|
|||
this.moduleToReader = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends to the given file path to the class path.
|
||||
*/
|
||||
void appendClassPath(String path) {
|
||||
// assert ucp != null;
|
||||
ucp.addFile(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the class path, called to reset the class path during -Xshare:dump
|
||||
*/
|
||||
void setClassPath(URLClassPath ucp) {
|
||||
this.ucp = ucp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if there is a class path associated with this
|
||||
* class loader.
|
||||
|
@ -1042,4 +1072,9 @@ public class BuiltinClassLoader
|
|||
private static URL checkURL(URL url) {
|
||||
return URLClassPath.checkURL(url);
|
||||
}
|
||||
|
||||
// Called from VM only, during -Xshare:dump
|
||||
private void resetArchivedStates() {
|
||||
ucp = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import java.util.jar.Manifest;
|
|||
import jdk.internal.access.JavaLangAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.module.ServicesCatalog;
|
||||
|
||||
/**
|
||||
* Creates and provides access to the built-in platform and application class
|
||||
|
@ -56,14 +57,22 @@ public class ClassLoaders {
|
|||
|
||||
// Creates the built-in class loaders.
|
||||
static {
|
||||
// -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute
|
||||
String append = VM.getSavedProperty("jdk.boot.class.path.append");
|
||||
BOOT_LOADER =
|
||||
new BootClassLoader((append != null && !append.isEmpty())
|
||||
? new URLClassPath(append, true)
|
||||
: null);
|
||||
PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);
|
||||
|
||||
ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get();
|
||||
if (archivedClassLoaders != null) {
|
||||
// assert VM.getSavedProperty("jdk.boot.class.path.append") == null
|
||||
BOOT_LOADER = (BootClassLoader) archivedClassLoaders.bootLoader();
|
||||
PLATFORM_LOADER = (PlatformClassLoader) archivedClassLoaders.platformLoader();
|
||||
ServicesCatalog catalog = archivedClassLoaders.servicesCatalog(PLATFORM_LOADER);
|
||||
ServicesCatalog.putServicesCatalog(PLATFORM_LOADER, catalog);
|
||||
} else {
|
||||
// -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute
|
||||
String append = VM.getSavedProperty("jdk.boot.class.path.append");
|
||||
URLClassPath ucp = (append != null && !append.isEmpty())
|
||||
? new URLClassPath(append, true)
|
||||
: null;
|
||||
BOOT_LOADER = new BootClassLoader(ucp);
|
||||
PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);
|
||||
}
|
||||
// A class path is required when no initial module is specified.
|
||||
// In this case the class path defaults to "", meaning the current
|
||||
// working directory. When an initial module is specified, on the
|
||||
|
@ -75,7 +84,15 @@ public class ClassLoaders {
|
|||
cp = (initialModuleName == null) ? "" : null;
|
||||
}
|
||||
URLClassPath ucp = new URLClassPath(cp, false);
|
||||
APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp);
|
||||
if (archivedClassLoaders != null) {
|
||||
APP_LOADER = (AppClassLoader) archivedClassLoaders.appLoader();
|
||||
ServicesCatalog catalog = archivedClassLoaders.servicesCatalog(APP_LOADER);
|
||||
ServicesCatalog.putServicesCatalog(APP_LOADER, catalog);
|
||||
APP_LOADER.setClassPath(ucp);
|
||||
} else {
|
||||
APP_LOADER = new AppClassLoader(PLATFORM_LOADER, ucp);
|
||||
ArchivedClassLoaders.archive();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,11 +161,8 @@ public class ClassLoaders {
|
|||
throw new InternalError();
|
||||
}
|
||||
|
||||
final URLClassPath ucp;
|
||||
|
||||
AppClassLoader(PlatformClassLoader parent, URLClassPath ucp) {
|
||||
AppClassLoader(BuiltinClassLoader parent, URLClassPath ucp) {
|
||||
super("app", parent, ucp);
|
||||
this.ucp = ucp;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -181,7 +195,7 @@ public class ClassLoaders {
|
|||
* @see java.lang.instrument.Instrumentation#appendToSystemClassLoaderSearch
|
||||
*/
|
||||
void appendToClassPathForInstrumentation(String path) {
|
||||
ucp.addFile(path);
|
||||
appendClassPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,6 +204,13 @@ public class ClassLoaders {
|
|||
protected Package defineOrCheckPackage(String pn, Manifest man, URL url) {
|
||||
return super.defineOrCheckPackage(pn, man, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the VM, during -Xshare:dump
|
||||
*/
|
||||
private void resetArchivedStates() {
|
||||
setClassPath(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -468,6 +468,8 @@ public class VM {
|
|||
*/
|
||||
public static native void initializeFromArchive(Class<?> c);
|
||||
|
||||
public static native void defineArchivedModules(ClassLoader platformLoader, ClassLoader systemLoader);
|
||||
|
||||
public static native long getRandomSeedForCDSDump();
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.module;
|
||||
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
/**
|
||||
* Used by ModuleBootstrap for archiving the boot layer and the builder needed to
|
||||
* set the IllegalAccessLogger.
|
||||
*/
|
||||
class ArchivedBootLayer {
|
||||
private static ArchivedBootLayer archivedBootLayer;
|
||||
|
||||
private final ModuleLayer bootLayer;
|
||||
private final IllegalAccessLogger.Builder builder;
|
||||
|
||||
private ArchivedBootLayer(ModuleLayer bootLayer,
|
||||
IllegalAccessLogger.Builder builder) {
|
||||
this.bootLayer = bootLayer;
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
ModuleLayer bootLayer() {
|
||||
return bootLayer;
|
||||
}
|
||||
|
||||
IllegalAccessLogger.Builder illegalAccessLoggerBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
static ArchivedBootLayer get() {
|
||||
return archivedBootLayer;
|
||||
}
|
||||
|
||||
static void archive(ModuleLayer layer, IllegalAccessLogger.Builder builder) {
|
||||
archivedBootLayer = new ArchivedBootLayer(layer, builder);
|
||||
}
|
||||
|
||||
static {
|
||||
VM.initializeFromArchive(ArchivedBootLayer.class);
|
||||
}
|
||||
}
|
|
@ -22,21 +22,20 @@
|
|||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
/**
|
||||
* Used by ModuleBootstrap to obtain the archived system modules and finder.
|
||||
* Used by ModuleBootstrap for archiving the configuration for the boot layer,
|
||||
* the system module finder, and the maps used to create the IllegalAccessLogger.
|
||||
*/
|
||||
final class ArchivedModuleGraph {
|
||||
class ArchivedModuleGraph {
|
||||
private static ArchivedModuleGraph archivedModuleGraph;
|
||||
|
||||
private final boolean hasSplitPackages;
|
||||
|
@ -47,13 +46,13 @@ final class ArchivedModuleGraph {
|
|||
private final Map<String, Set<String>> concealedPackagesToOpen;
|
||||
private final Map<String, Set<String>> exportedPackagesToOpen;
|
||||
|
||||
public ArchivedModuleGraph(boolean hasSplitPackages,
|
||||
boolean hasIncubatorModules,
|
||||
ModuleFinder finder,
|
||||
Configuration configuration,
|
||||
Function<String, ClassLoader> classLoaderFunction,
|
||||
Map<String, Set<String>> concealedPackagesToOpen,
|
||||
Map<String, Set<String>> exportedPackagesToOpen) {
|
||||
private 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;
|
||||
|
@ -107,8 +106,20 @@ final class ArchivedModuleGraph {
|
|||
/**
|
||||
* Archive the module graph for the given initial module.
|
||||
*/
|
||||
static void archive(ArchivedModuleGraph graph) {
|
||||
archivedModuleGraph = graph;
|
||||
static void archive(boolean hasSplitPackages,
|
||||
boolean hasIncubatorModules,
|
||||
ModuleFinder finder,
|
||||
Configuration configuration,
|
||||
Function<String, ClassLoader> classLoaderFunction,
|
||||
Map<String, Set<String>> concealedPackagesToOpen,
|
||||
Map<String, Set<String>> exportedPackagesToOpen) {
|
||||
archivedModuleGraph = new ArchivedModuleGraph(hasSplitPackages,
|
||||
hasIncubatorModules,
|
||||
finder,
|
||||
configuration,
|
||||
classLoaderFunction,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen);
|
||||
}
|
||||
|
||||
static {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 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
|
||||
|
@ -57,7 +57,7 @@ public final class IllegalAccessLogger {
|
|||
/**
|
||||
* Logger modes
|
||||
*/
|
||||
public static enum Mode {
|
||||
public enum Mode {
|
||||
/**
|
||||
* Prints a warning when an illegal access succeeds and then
|
||||
* discards the logger so that there is no further output.
|
||||
|
@ -118,7 +118,7 @@ public final class IllegalAccessLogger {
|
|||
}
|
||||
|
||||
/**
|
||||
* Builds the IllegalAccessLogger and sets it as the system-wise logger.
|
||||
* Builds the IllegalAccessLogger and sets it as the system-wide logger.
|
||||
*/
|
||||
public void complete() {
|
||||
Map<Module, Set<String>> map1 = unmodifiableMap(moduleToConcealedPackages);
|
||||
|
|
|
@ -42,18 +42,19 @@ import java.util.Iterator;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
import jdk.internal.access.JavaLangAccess;
|
||||
import jdk.internal.access.JavaLangModuleAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.loader.BootLoader;
|
||||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
import jdk.internal.loader.ClassLoaders;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.perf.PerfCounter;
|
||||
|
||||
/**
|
||||
|
@ -86,8 +87,8 @@ public final class ModuleBootstrap {
|
|||
private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
|
||||
|
||||
// access to java.lang/module
|
||||
private static final JavaLangModuleAccess JLMA
|
||||
= SharedSecrets.getJavaLangModuleAccess();
|
||||
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
||||
private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
|
||||
|
||||
// The ModulePatcher for the initial configuration
|
||||
private static final ModulePatcher patcher = initModulePatcher();
|
||||
|
@ -134,14 +135,58 @@ public final class ModuleBootstrap {
|
|||
}
|
||||
|
||||
/**
|
||||
* Initialize the module system, returning the boot layer.
|
||||
* Returns true if the archived boot layer can be used. The system properties
|
||||
* are checked in the order that they are used by boot2.
|
||||
*/
|
||||
private static boolean canUseArchivedBootLayer() {
|
||||
return getProperty("jdk.module.upgrade.path") == null &&
|
||||
getProperty("jdk.module.path") == null &&
|
||||
getProperty("jdk.module.patch.0") == null && // --patch-module
|
||||
getProperty("jdk.module.main") == null &&
|
||||
getProperty("jdk.module.addmods.0") == null && // --add-modules
|
||||
getProperty("jdk.module.limitmods") == null &&
|
||||
getProperty("jdk.module.addreads.0") == null && // --add-reads
|
||||
getProperty("jdk.module.addexports.0") == null && // --add-exports
|
||||
getProperty("jdk.module.addopens.0") == null && // --add-opens
|
||||
getProperty("jdk.module.illegalAccess") == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the module system, returning the boot layer. The boot layer
|
||||
* is obtained from the CDS archive if possible, otherwise it is generated
|
||||
* from the module graph.
|
||||
*
|
||||
* @see java.lang.System#initPhase2(boolean, boolean)
|
||||
*/
|
||||
public static ModuleLayer boot() throws Exception {
|
||||
|
||||
public static ModuleLayer boot() {
|
||||
Counters.start();
|
||||
|
||||
ModuleLayer bootLayer;
|
||||
ArchivedBootLayer archivedBootLayer = ArchivedBootLayer.get();
|
||||
if (archivedBootLayer != null) {
|
||||
assert canUseArchivedBootLayer();
|
||||
bootLayer = archivedBootLayer.bootLayer();
|
||||
BootLoader.getUnnamedModule(); // trigger <clinit> of BootLoader.
|
||||
VM.defineArchivedModules(ClassLoaders.platformClassLoader(), ClassLoaders.appClassLoader());
|
||||
|
||||
// assume boot layer has at least one module providing a service
|
||||
// that is mapped to the application class loader.
|
||||
JLA.bindToLoader(bootLayer, ClassLoaders.appClassLoader());
|
||||
|
||||
// IllegalAccessLogger needs to be set
|
||||
var illegalAccessLoggerBuilder = archivedBootLayer.illegalAccessLoggerBuilder();
|
||||
if (illegalAccessLoggerBuilder != null) {
|
||||
illegalAccessLoggerBuilder.complete();
|
||||
}
|
||||
} else {
|
||||
bootLayer = boot2();
|
||||
}
|
||||
|
||||
Counters.publish("jdk.module.boot.totalTime");
|
||||
return bootLayer;
|
||||
}
|
||||
|
||||
private static ModuleLayer boot2() {
|
||||
// Step 0: Command line options
|
||||
|
||||
ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
|
||||
|
@ -428,11 +473,12 @@ public final class ModuleBootstrap {
|
|||
concealedPackagesToOpen = systemModules.concealedPackagesToOpen();
|
||||
exportedPackagesToOpen = systemModules.exportedPackagesToOpen();
|
||||
}
|
||||
addIllegalAccess(upgradeModulePath,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen,
|
||||
bootLayer,
|
||||
extraExportsOrOpens);
|
||||
IllegalAccessLogger.Builder builder =
|
||||
addIllegalAccess(upgradeModulePath,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen,
|
||||
bootLayer,
|
||||
extraExportsOrOpens);
|
||||
Counters.add("jdk.module.boot.7.adjustModulesTime");
|
||||
|
||||
// save module finders for later use
|
||||
|
@ -442,21 +488,21 @@ public final class ModuleBootstrap {
|
|||
limitedFinder = new SafeModuleFinder(finder);
|
||||
}
|
||||
|
||||
// Module graph can be archived at CDS dump time. Only allow the
|
||||
// unnamed module case for now.
|
||||
// Archive module graph and boot layer can be archived at CDS dump time.
|
||||
// Only allow the unnamed module case for now.
|
||||
if (canArchive && (mainModule == null)) {
|
||||
ArchivedModuleGraph.archive(
|
||||
new ArchivedModuleGraph(hasSplitPackages,
|
||||
hasIncubatorModules,
|
||||
systemModuleFinder,
|
||||
cf,
|
||||
clf,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen));
|
||||
}
|
||||
ArchivedModuleGraph.archive(hasSplitPackages,
|
||||
hasIncubatorModules,
|
||||
systemModuleFinder,
|
||||
cf,
|
||||
clf,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen);
|
||||
|
||||
// total time to initialize
|
||||
Counters.publish("jdk.module.boot.totalTime");
|
||||
if (!hasSplitPackages && !hasIncubatorModules) {
|
||||
ArchivedBootLayer.archive(bootLayer, builder);
|
||||
}
|
||||
}
|
||||
|
||||
return bootLayer;
|
||||
}
|
||||
|
@ -751,17 +797,18 @@ public final class ModuleBootstrap {
|
|||
* Process the --illegal-access option (and its default) to open packages
|
||||
* of system modules in the boot layer to code in unnamed modules.
|
||||
*/
|
||||
private static void addIllegalAccess(ModuleFinder upgradeModulePath,
|
||||
Map<String, Set<String>> concealedPackagesToOpen,
|
||||
Map<String, Set<String>> exportedPackagesToOpen,
|
||||
ModuleLayer bootLayer,
|
||||
boolean extraExportsOrOpens) {
|
||||
private static IllegalAccessLogger.Builder
|
||||
addIllegalAccess(ModuleFinder upgradeModulePath,
|
||||
Map<String, Set<String>> concealedPackagesToOpen,
|
||||
Map<String, Set<String>> exportedPackagesToOpen,
|
||||
ModuleLayer bootLayer,
|
||||
boolean extraExportsOrOpens) {
|
||||
String value = getAndRemoveProperty("jdk.module.illegalAccess");
|
||||
IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT;
|
||||
if (value != null) {
|
||||
switch (value) {
|
||||
case "deny":
|
||||
return;
|
||||
return null;
|
||||
case "permit":
|
||||
break;
|
||||
case "warn":
|
||||
|
@ -773,7 +820,7 @@ public final class ModuleBootstrap {
|
|||
default:
|
||||
fail("Value specified to --illegal-access not recognized:"
|
||||
+ " '" + value + "'");
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
IllegalAccessLogger.Builder builder
|
||||
|
@ -836,11 +883,11 @@ public final class ModuleBootstrap {
|
|||
builder.logAccessToExportedPackages(m, exportedPackages);
|
||||
|
||||
// open the packages to unnamed modules
|
||||
JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
|
||||
jla.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
|
||||
JLA.addOpensToAllUnnamed(m, concealedPackages, exportedPackages);
|
||||
}
|
||||
|
||||
builder.complete();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -905,11 +952,19 @@ public final class ModuleBootstrap {
|
|||
return decode(prefix, ",", true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the named system property
|
||||
*/
|
||||
private static String getProperty(String key) {
|
||||
return System.getProperty(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and remove the named system property
|
||||
*/
|
||||
private static String getAndRemoveProperty(String key) {
|
||||
return (String)System.getProperties().remove(key);
|
||||
return (String) System.getProperties().remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -171,6 +171,16 @@ public final class ServicesCatalog {
|
|||
return catalog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the given ServicesCatalog with the given class loader.
|
||||
*/
|
||||
public static void putServicesCatalog(ClassLoader loader, ServicesCatalog catalog) {
|
||||
ServicesCatalog previous = CLV.putIfAbsent(loader, catalog);
|
||||
if (previous != null) {
|
||||
throw new InternalError();
|
||||
}
|
||||
}
|
||||
|
||||
// the ServicesCatalog registered to a class loader
|
||||
private static final ClassLoaderValue<ServicesCatalog> CLV = new ClassLoaderValue<>();
|
||||
}
|
||||
|
|
|
@ -62,6 +62,13 @@ Java_jdk_internal_misc_VM_initializeFromArchive(JNIEnv *env, jclass ignore,
|
|||
JVM_InitializeFromArchive(env, c);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_jdk_internal_misc_VM_defineArchivedModules(JNIEnv *env, jclass ignore,
|
||||
jobject platform_loader,
|
||||
jobject system_loader) {
|
||||
JVM_DefineArchivedModules(env, platform_loader, system_loader);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_jdk_internal_misc_VM_getRandomSeedForCDSDump(JNIEnv *env, jclass ignore) {
|
||||
return JVM_GetRandomSeedForCDSDump();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue