8308464: Shared array class should not always be loaded in boot loader

Reviewed-by: dholmes, iklam
This commit is contained in:
Calvin Cheung 2023-08-28 22:05:15 +00:00
parent 69d1feb83f
commit 1cb2cc6587
4 changed files with 32 additions and 15 deletions

View File

@ -175,7 +175,6 @@ void ArrayKlass::remove_java_mirror() {
}
void ArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
assert(loader_data == ClassLoaderData::the_null_class_loader_data(), "array classes belong to null loader");
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
// Klass recreates the component mirror also

View File

@ -2703,10 +2703,11 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
if (array_klasses() != nullptr) {
// To get a consistent list of classes we need MultiArray_lock to ensure
// array classes aren't observed while they are being restored.
MutexLocker ml(MultiArray_lock);
MutexLocker ml(MultiArray_lock);
assert(this == array_klasses()->bottom_klass(), "sanity");
// Array classes have null protection domain.
// --> see ArrayKlass::complete_create_array_klass()
array_klasses()->restore_unshareable_info(ClassLoaderData::the_null_class_loader_data(), Handle(), CHECK);
array_klasses()->restore_unshareable_info(class_loader_data(), Handle(), CHECK);
}
// Initialize @ValueBased class annotation

View File

@ -570,7 +570,9 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
JFR_ONLY(RESTORE_ID(this);)
if (log_is_enabled(Trace, cds, unshareable)) {
ResourceMark rm(THREAD);
log_trace(cds, unshareable)("restore: %s", external_name());
oop class_loader = loader_data->class_loader();
log_trace(cds, unshareable)("restore: %s with class loader: %s", external_name(),
class_loader != nullptr ? class_loader->klass()->external_name() : "boot");
}
// If an exception happened during CDS restore, some of these fields may already be

View File

@ -44,8 +44,10 @@ public class ArrayKlasses extends DynamicArchiveTestBase {
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("ArrayKlasses.jar");
String mainClass = "ArrayKlassesApp";
final String appJar = ClassFileInstaller.getJarPath("ArrayKlasses.jar");
final String mainClass = "ArrayKlassesApp";
final String runtimeLogOptions =
"-Xlog:class+load,class+load+array=debug,cds+dynamic=debug,cds=debug,cds+unshareable=trace";
// Case 1
// Create a dynamic archive with the ArrayKlassesApp app class and its
@ -62,14 +64,17 @@ public class ArrayKlasses extends DynamicArchiveTestBase {
// Case 1
// At runtime , the ArrayKlasesApp and its array class should be loaded
// from the dynamic archive.
run2(null, topArchiveName,
"-Xlog:class+load,class+load+array=debug,cds+dynamic=debug,cds=debug",
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("ArrayKlassesApp source: shared objects file (top)")
.shouldContain("restore: ArrayKlassesApp with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldContain("[LArrayKlassesApp; source: shared objects file (top)")
.shouldContain("restore: [LArrayKlassesApp; with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldContain("[[LArrayKlassesApp; source: shared objects file (top)")
.shouldContain("restore: [[LArrayKlassesApp; with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldContain("[[[LArrayKlassesApp; source: shared objects file (top)")
.shouldContain("restore: [[[LArrayKlassesApp; with class loader: jdk.internal.loader.ClassLoaders$AppClassLoader")
.shouldHaveExitValue(0);
});
@ -90,14 +95,17 @@ public class ArrayKlasses extends DynamicArchiveTestBase {
// Case 2
// At runtime, the java/util/Date class should be loaded from the default
// CDS archive; its array class should be loaded from the dynamic archive.
run2(null, topArchiveName,
"-Xlog:class+load,class+load+array=debug,cds+dynamic=debug,cds=debug",
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass, "system")
.assertNormalExit(output -> {
output.shouldContain("java.util.Date source: shared objects file")
.shouldContain("restore: java.util.Date with class loader: boot")
.shouldContain("[Ljava.util.Date; source: shared objects file (top)")
.shouldContain("restore: [Ljava.util.Date; with class loader: boot")
.shouldContain("[[Ljava.util.Date; source: shared objects file (top)")
.shouldContain("restore: [[Ljava.util.Date; with class loader: boot")
.shouldContain("[[[Ljava.util.Date; source: shared objects file (top)")
.shouldContain("restore: [[[Ljava.util.Date; with class loader: boot")
.shouldHaveExitValue(0);
});
@ -116,13 +124,15 @@ public class ArrayKlasses extends DynamicArchiveTestBase {
// Case 3
// At runtime, the [J should be loaded from the default CDS archive;
// the higher-dimension array should be loaded from the dynamic archive.
run2(null, topArchiveName,
"-Xlog:class+load,class+load+array=debug,cds+dynamic=debug,cds=debug",
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass, "primitive")
.assertNormalExit(output -> {
output.shouldContain("[J source: shared objects file")
.shouldContain("restore: [J with class loader: boot")
.shouldContain("[[J source: shared objects file (top)")
.shouldContain("restore: [[J with class loader: boot")
.shouldContain("[[[J source: shared objects file (top)")
.shouldContain("restore: [[[J with class loader: boot")
.shouldHaveExitValue(0);
});
@ -142,13 +152,18 @@ public class ArrayKlasses extends DynamicArchiveTestBase {
// Case 4
// At runtime, the 4-dimension array of java/lang/Integer should be
// loaded from the dynamic archive.
run2(null, topArchiveName,
"-Xlog:class+load,class+load+array=debug,cds+dynamic=debug,cds=debug",
run2(null, topArchiveName, runtimeLogOptions,
"-cp", appJar, mainClass, "integer-array")
.assertNormalExit(output -> {
output.shouldContain("[[Ljava.lang.Integer; source: shared objects file (top)")
output.shouldContain("java.lang.Integer source: shared objects file")
.shouldContain("restore: java.lang.Integer with class loader: boot")
.shouldContain("restore: [Ljava.lang.Integer; with class loader: boot")
.shouldContain("[[Ljava.lang.Integer; source: shared objects file (top)")
.shouldContain("restore: [[Ljava.lang.Integer; with class loader: boot")
.shouldContain("[[[Ljava.lang.Integer; source: shared objects file (top)")
.shouldContain("restore: [[[Ljava.lang.Integer; with class loader: boot")
.shouldContain("[[[[Ljava.lang.Integer; source: shared objects file (top)")
.shouldContain("restore: [[[[Ljava.lang.Integer; with class loader: boot")
.shouldHaveExitValue(0);
});
}