# HG changeset patch # User ccheung # Date 1525278370 25200 # Node ID ff8dbb56740af64a6030f0c53b7125dd10a47733 # Parent cece972575acac82eea5c840a4441f43f35f7f8a 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 diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/classfile/classFileParser.cpp --- 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(_super_klass), CHECK); + ik->initialize_supers(const_cast(_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 diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/memory/universe.cpp --- 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(); } diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/arrayKlass.cpp --- 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* ArrayKlass::compute_secondary_supers(int num_extra_slots) { +GrowableArray* ArrayKlass::compute_secondary_supers(int num_extra_slots, + Array* 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; diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/arrayKlass.hpp --- 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(k); } - GrowableArray* compute_secondary_supers(int num_extra_slots); + GrowableArray* compute_secondary_supers(int num_extra_slots, + Array* transitive_interfaces); bool compute_is_subtype_of(Klass* k); // Sizing diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/instanceKlass.cpp --- 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* InstanceKlass::compute_secondary_supers(int num_extra_slots) { +GrowableArray* InstanceKlass::compute_secondary_supers(int num_extra_slots, + Array* transitive_interfaces) { // The secondaries are the implemented interfaces. - Array* interfaces = transitive_interfaces(); + Array* interfaces = transitive_interfaces; int num_secondaries = num_extra_slots + interfaces->length(); if (num_secondaries == 0) { // Must share this for correct bootstrapping! diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/instanceKlass.hpp --- 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* compute_secondary_supers(int num_extra_slots); + GrowableArray* compute_secondary_supers(int num_extra_slots, + Array* 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(); } diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/klass.cpp --- 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* 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* secondaries = compute_secondary_supers(extras); + GrowableArray* secondaries = compute_secondary_supers(extras, transitive_interfaces); if (secondaries == NULL) { // secondary_supers set by compute_secondary_supers return; @@ -342,8 +342,10 @@ } } -GrowableArray* Klass::compute_secondary_supers(int num_extra_slots) { +GrowableArray* Klass::compute_secondary_supers(int num_extra_slots, + Array* 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; } diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/klass.hpp --- 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* transitive_interfaces, TRAPS); void initialize_supers_impl1(Klass* k); void initialize_supers_impl2(Klass* k); // klass-specific helper for initializing _secondary_supers - virtual GrowableArray* compute_secondary_supers(int num_extra_slots); + virtual GrowableArray* compute_secondary_supers(int num_extra_slots, + Array* transitive_interfaces); // java_super is the Java-level super type as specified by Class.getSuperClass. virtual Klass* java_super() const { return NULL; } diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/objArrayKlass.cpp --- 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* ObjArrayKlass::compute_secondary_supers(int num_extra_slots) { +GrowableArray* ObjArrayKlass::compute_secondary_supers(int num_extra_slots, + Array* transitive_interfaces) { + assert(transitive_interfaces == NULL, "sanity"); // interfaces = { cloneable_klass, serializable_klass, elemSuper[], ... }; Array* elem_supers = element_klass()->secondary_supers(); int num_elem_supers = elem_supers == NULL ? 0 : elem_supers->length(); diff -r cece972575ac -r ff8dbb56740a src/hotspot/share/oops/objArrayKlass.hpp --- 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* compute_secondary_supers(int num_extra_slots); + GrowableArray* compute_secondary_supers(int num_extra_slots, + Array* 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;