diff --git a/src/hotspot/share/oops/arrayKlass.cpp b/src/hotspot/share/oops/arrayKlass.cpp index e2057b6a9fc..ecc3da7bd5d 100644 --- a/src/hotspot/share/oops/arrayKlass.cpp +++ b/src/hotspot/share/oops/arrayKlass.cpp @@ -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 diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index d157229d22d..24b9dfe8789 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -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 diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 4ebcc5329c0..036386e7e3e 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -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 diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArrayKlasses.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArrayKlasses.java index 991bebe5a59..db2b4718fd2 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArrayKlasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArrayKlasses.java @@ -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); }); }