diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java index b890ba51651d4..0fbb887dc5113 100644 --- a/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/src/java.base/share/classes/java/lang/ClassLoader.java @@ -64,6 +64,7 @@ import jdk.internal.reflect.CallerSensitiveAdapter; import jdk.internal.reflect.Reflection; import jdk.internal.util.StaticProperty; +import jdk.internal.vm.annotation.Stable; /** * A class loader is an object that is responsible for loading classes. The @@ -290,10 +291,10 @@ static boolean isRegistered(Class c) { // class loader is parallel capable. // Note: VM also uses this field to decide if the current class loader // is parallel capable and the appropriate lock object for class loading. - private final ConcurrentHashMap parallelLockMap; + private @Stable ConcurrentHashMap parallelLockMap; // Maps packages to certs - private final ConcurrentHashMap package2certs; + private @Stable ConcurrentHashMap package2certs; // Shared among all packages with unsigned classes private static final Certificate[] nocerts = new Certificate[0]; @@ -322,7 +323,7 @@ void addClass(Class c) { // Class::getPackage, ClassLoader::getDefinePackage(s) or // Package::getPackage(s) method is called to define it. // Otherwise, the value is a NamedPackage object. - private final ConcurrentHashMap packages + private @Stable ConcurrentHashMap packages = new ConcurrentHashMap<>(); /* @@ -2572,15 +2573,20 @@ private boolean trySetObjectField(String name, Object obj) { } /** - * Called by the VM, during -Xshare:dump + * Called only by the VM, during -Xshare:dump. + * + * @implNote This is done while the JVM is running in single-threaded mode, + * and at the very end of Java bytecode execution. We know that no more classes + * will be loaded and none of the fields modified by this method will be used again. */ private void resetArchivedStates() { if (parallelLockMap != null) { - parallelLockMap.clear(); + parallelLockMap = new ConcurrentHashMap<>(); } - packages.clear(); - package2certs.clear(); - classes.clear(); + packages = new ConcurrentHashMap<>(); + package2certs = new ConcurrentHashMap<>(); + classes.clear(); + classes.trimToSize(); classLoaderValueMap = null; } }