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
--- 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;