8210926: vmTestbase/nsk/jvmti/scenarios/allocation/AP11/ap11t001/TestDescription.java failed with JVMTI_ERROR_INVALID_CLASS in CDS mode
authorjiangli
Mon, 01 Oct 2018 00:52:37 -0400
changeset 51962 628909466216
parent 51961 540c1a848dd8
child 51964 d034d46065fb
8210926: vmTestbase/nsk/jvmti/scenarios/allocation/AP11/ap11t001/TestDescription.java failed with JVMTI_ERROR_INVALID_CLASS in CDS mode Summary: Reset InstanceKlass _init_state to 'allocated' before writing out shared classes at dump time. Reviewed-by: dholmes, coleenp
src/hotspot/share/classfile/classLoaderData.cpp
src/hotspot/share/oops/instanceKlass.cpp
src/hotspot/share/oops/instanceKlass.hpp
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Fri Sep 28 14:53:41 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Mon Oct 01 00:52:37 2018 -0400
@@ -338,6 +338,11 @@
   for (Klass* k = OrderAccess::load_acquire(&_klasses); k != NULL; k = k->next_link()) {
     // Do not filter ArrayKlass oops here...
     if (k->is_array_klass() || (k->is_instance_klass() && InstanceKlass::cast(k)->is_loaded())) {
+#ifdef ASSERT
+      oop m = k->java_mirror();
+      assert(m != NULL, "NULL mirror");
+      assert(m->is_a(SystemDictionary::Class_klass()), "invalid mirror");
+#endif
       klass_closure->do_klass(k);
     }
   }
--- a/src/hotspot/share/oops/instanceKlass.cpp	Fri Sep 28 14:53:41 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Mon Oct 01 00:52:37 2018 -0400
@@ -686,15 +686,6 @@
   return Verifier::verify(this, should_verify_class(), THREAD);
 }
 
-
-// Used exclusively by the shared spaces dump mechanism to prevent
-// classes mapped into the shared regions in new VMs from appearing linked.
-
-void InstanceKlass::unlink_class() {
-  assert(is_linked(), "must be linked");
-  _init_state = loaded;
-}
-
 void InstanceKlass::link_class(TRAPS) {
   assert(is_loaded(), "must be loaded");
   if (!is_linked()) {
@@ -2300,10 +2291,12 @@
     return;
   }
 
-  // Unlink the class
-  if (is_linked()) {
-    unlink_class();
-  }
+  // Reset to the 'allocated' state to prevent any premature accessing to
+  // a shared class at runtime while the class is still being loaded and
+  // restored. A class' init_state is set to 'loaded' at runtime when it's
+  // being added to class hierarchy (see SystemDictionary:::add_to_hierarchy()).
+  _init_state = allocated;
+
   {
     MutexLocker ml(Compile_lock);
     init_implementor();
@@ -2350,6 +2343,10 @@
 }
 
 void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
+  // SystemDictionary::add_to_hierarchy() sets the init_state to loaded
+  // before the InstanceKlass is added to the SystemDictionary. Make
+  // sure the current state is <loaded.
+  assert(!is_loaded(), "invalid init state");
   set_package(loader_data, CHECK);
   Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
 
--- a/src/hotspot/share/oops/instanceKlass.hpp	Fri Sep 28 14:53:41 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Mon Oct 01 00:52:37 2018 -0400
@@ -542,7 +542,6 @@
   void initialize(TRAPS);
   void link_class(TRAPS);
   bool link_class_or_fail(TRAPS); // returns false on failure
-  void unlink_class();
   void rewrite_class(TRAPS);
   void link_methods(TRAPS);
   Method* class_initializer() const;