8200466: Revisit the setting of _transitive_interfaces in InstanceKlass
authorccheung
Wed, 02 May 2018 09:26:10 -0700
changeset 49948 ff8dbb56740a
parent 49947 cece972575ac
child 49949 c8684fac37bb
8200466: Revisit the setting of _transitive_interfaces in InstanceKlass Summary: Delay the setting of _transitive_interfaces until after initialize_supers() in fill_instance_klass(). Reviewed-by: iklam, coleenp
src/hotspot/share/classfile/classFileParser.cpp
src/hotspot/share/memory/universe.cpp
src/hotspot/share/oops/arrayKlass.cpp
src/hotspot/share/oops/arrayKlass.hpp
src/hotspot/share/oops/instanceKlass.cpp
src/hotspot/share/oops/instanceKlass.hpp
src/hotspot/share/oops/klass.cpp
src/hotspot/share/oops/klass.hpp
src/hotspot/share/oops/objArrayKlass.cpp
src/hotspot/share/oops/objArrayKlass.hpp
--- a/src/hotspot/share/classfile/classFileParser.cpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Wed May 02 09:26:10 2018 -0700
@@ -3592,8 +3592,13 @@
   this_klass->set_methods(_methods);
   this_klass->set_inner_classes(_inner_classes);
   this_klass->set_local_interfaces(_local_interfaces);
-  this_klass->set_transitive_interfaces(_transitive_interfaces);
   this_klass->set_annotations(_combined_annotations);
+  // Delay the setting of _transitive_interfaces until after initialize_supers() in
+  // fill_instance_klass(). It is because the _transitive_interfaces may be shared with
+  // its _super. If an OOM occurs while loading the current klass, its _super field
+  // may not have been set. When GC tries to free the klass, the _transitive_interfaces
+  // may be deallocated mistakenly in InstanceKlass::deallocate_interfaces(). Subsequent
+  // dereferences to the deallocated _transitive_interfaces will result in a crash.
 
   // Clear out these fields so they don't get deallocated by the destructor
   clear_class_metadata();
@@ -5462,7 +5467,6 @@
   assert(NULL == _methods, "invariant");
   assert(NULL == _inner_classes, "invariant");
   assert(NULL == _local_interfaces, "invariant");
-  assert(NULL == _transitive_interfaces, "invariant");
   assert(NULL == _combined_annotations, "invariant");
 
   if (_has_final_method) {
@@ -5529,7 +5533,9 @@
   }
 
   // Fill in information needed to compute superclasses.
-  ik->initialize_supers(const_cast<InstanceKlass*>(_super_klass), CHECK);
+  ik->initialize_supers(const_cast<InstanceKlass*>(_super_klass), _transitive_interfaces, CHECK);
+  ik->set_transitive_interfaces(_transitive_interfaces);
+  _transitive_interfaces = NULL;
 
   // Initialize itable offset tables
   klassItable::setup_itable_offset_table(ik);
@@ -5834,7 +5840,6 @@
   _methods = NULL;
   _inner_classes = NULL;
   _local_interfaces = NULL;
-  _transitive_interfaces = NULL;
   _combined_annotations = NULL;
   _annotations = _type_annotations = NULL;
   _fields_annotations = _fields_type_annotations = NULL;
@@ -5886,6 +5891,7 @@
   }
 
   clear_class_metadata();
+  _transitive_interfaces = NULL;
 
   // deallocate the klass if already created.  Don't directly deallocate, but add
   // to the deallocate list so that the klass is removed from the CLD::_klasses list
--- a/src/hotspot/share/memory/universe.cpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/memory/universe.cpp	Wed May 02 09:26:10 2018 -0700
@@ -318,7 +318,7 @@
   } else
 #endif
   {
-    k->initialize_supers(ok, CHECK);
+    k->initialize_supers(ok, NULL, CHECK);
   }
   k->append_to_sibling_list();
 }
--- a/src/hotspot/share/oops/arrayKlass.cpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/arrayKlass.cpp	Wed May 02 09:26:10 2018 -0700
@@ -99,7 +99,7 @@
 // since a GC can happen. At this point all instance variables of the ArrayKlass must be setup.
 void ArrayKlass::complete_create_array_klass(ArrayKlass* k, Klass* super_klass, ModuleEntry* module_entry, TRAPS) {
   ResourceMark rm(THREAD);
-  k->initialize_supers(super_klass, CHECK);
+  k->initialize_supers(super_klass, NULL, CHECK);
   k->vtable().initialize_vtable(false, CHECK);
 
   // During bootstrapping, before java.base is defined, the module_entry may not be present yet.
@@ -111,9 +111,11 @@
   java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(), CHECK);
 }
 
-GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots) {
+GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots,
+                                                            Array<Klass*>* transitive_interfaces) {
   // interfaces = { cloneable_klass, serializable_klass };
   assert(num_extra_slots == 0, "sanity of primitive array type");
+  assert(transitive_interfaces == NULL, "sanity");
   // Must share this for correct bootstrapping!
   set_secondary_supers(Universe::the_array_interfaces_array());
   return NULL;
--- a/src/hotspot/share/oops/arrayKlass.hpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/arrayKlass.hpp	Wed May 02 09:26:10 2018 -0700
@@ -98,7 +98,8 @@
     return static_cast<const ArrayKlass*>(k);
   }
 
-  GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
+  GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots,
+                                                  Array<Klass*>* transitive_interfaces);
   bool compute_is_subtype_of(Klass* k);
 
   // Sizing
--- a/src/hotspot/share/oops/instanceKlass.cpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Wed May 02 09:26:10 2018 -0700
@@ -918,9 +918,10 @@
     return Klass::can_be_primary_super_slow();
 }
 
-GrowableArray<Klass*>* InstanceKlass::compute_secondary_supers(int num_extra_slots) {
+GrowableArray<Klass*>* InstanceKlass::compute_secondary_supers(int num_extra_slots,
+                                                               Array<Klass*>* transitive_interfaces) {
   // The secondaries are the implemented interfaces.
-  Array<Klass*>* interfaces = transitive_interfaces();
+  Array<Klass*>* interfaces = transitive_interfaces;
   int num_secondaries = num_extra_slots + interfaces->length();
   if (num_secondaries == 0) {
     // Must share this for correct bootstrapping!
--- a/src/hotspot/share/oops/instanceKlass.hpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Wed May 02 09:26:10 2018 -0700
@@ -1013,7 +1013,8 @@
 
   // virtual operations from Klass
   bool is_leaf_class() const               { return _subklass == NULL; }
-  GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
+  GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots,
+                                                  Array<Klass*>* transitive_interfaces);
   bool compute_is_subtype_of(Klass* k);
   bool can_be_primary_super_slow() const;
   int oop_size(oop obj)  const             { return size_helper(); }
--- a/src/hotspot/share/oops/klass.cpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/klass.cpp	Wed May 02 09:26:10 2018 -0700
@@ -224,7 +224,7 @@
     return true;
 }
 
-void Klass::initialize_supers(Klass* k, TRAPS) {
+void Klass::initialize_supers(Klass* k, Array<Klass*>* transitive_interfaces, TRAPS) {
   if (FastSuperclassLimit == 0) {
     // None of the other machinery matters.
     set_super(k);
@@ -292,7 +292,7 @@
     ResourceMark rm(THREAD);  // need to reclaim GrowableArrays allocated below
 
     // Compute the "real" non-extra secondaries.
-    GrowableArray<Klass*>* secondaries = compute_secondary_supers(extras);
+    GrowableArray<Klass*>* secondaries = compute_secondary_supers(extras, transitive_interfaces);
     if (secondaries == NULL) {
       // secondary_supers set by compute_secondary_supers
       return;
@@ -342,8 +342,10 @@
   }
 }
 
-GrowableArray<Klass*>* Klass::compute_secondary_supers(int num_extra_slots) {
+GrowableArray<Klass*>* Klass::compute_secondary_supers(int num_extra_slots,
+                                                       Array<Klass*>* transitive_interfaces) {
   assert(num_extra_slots == 0, "override for complex klasses");
+  assert(transitive_interfaces == NULL, "sanity");
   set_secondary_supers(Universe::the_empty_klass_array());
   return NULL;
 }
--- a/src/hotspot/share/oops/klass.hpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/klass.hpp	Wed May 02 09:26:10 2018 -0700
@@ -189,12 +189,13 @@
   void set_super(Klass* k)           { _super = k; }
 
   // initializes _super link, _primary_supers & _secondary_supers arrays
-  void initialize_supers(Klass* k, TRAPS);
+  void initialize_supers(Klass* k, Array<Klass*>* transitive_interfaces, TRAPS);
   void initialize_supers_impl1(Klass* k);
   void initialize_supers_impl2(Klass* k);
 
   // klass-specific helper for initializing _secondary_supers
-  virtual GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
+  virtual GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots,
+                                                          Array<Klass*>* transitive_interfaces);
 
   // java_super is the Java-level super type as specified by Class.getSuperClass.
   virtual Klass* java_super() const  { return NULL; }
--- a/src/hotspot/share/oops/objArrayKlass.cpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/objArrayKlass.cpp	Wed May 02 09:26:10 2018 -0700
@@ -331,7 +331,9 @@
     return Klass::can_be_primary_super_slow();
 }
 
-GrowableArray<Klass*>* ObjArrayKlass::compute_secondary_supers(int num_extra_slots) {
+GrowableArray<Klass*>* ObjArrayKlass::compute_secondary_supers(int num_extra_slots,
+                                                               Array<Klass*>* transitive_interfaces) {
+  assert(transitive_interfaces == NULL, "sanity");
   // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... };
   Array<Klass*>* elem_supers = element_klass()->secondary_supers();
   int num_elem_supers = elem_supers == NULL ? 0 : elem_supers->length();
--- a/src/hotspot/share/oops/objArrayKlass.hpp	Wed May 02 15:29:55 2018 +0100
+++ b/src/hotspot/share/oops/objArrayKlass.hpp	Wed May 02 09:26:10 2018 -0700
@@ -64,7 +64,8 @@
 
   // Dispatched operation
   bool can_be_primary_super_slow() const;
-  GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
+  GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots,
+                                                  Array<Klass*>* transitive_interfaces);
   bool compute_is_subtype_of(Klass* k);
   DEBUG_ONLY(bool is_objArray_klass_slow()  const  { return true; })
   int oop_size(oop obj) const;