RFR(S): 8200466: Revisit the setting of _transitive_interfaces in InstanceKlass
coleen.phillimore at oracle.com
coleen.phillimore at oracle.com
Tue May 1 17:29:48 UTC 2018
Hi Calvin,
Ok, I had a look at this. It seems that the relative initialization
orders of _super and the primary superclasses is unfathonably complicated.
I'm fine with your initial change as is.
Thanks,
Coleen
On 4/30/18 8:24 PM, Calvin Cheung wrote:
> Hi Coleen,
>
> I've tried the following simple change:
>
> --- a/src/hotspot/share/classfile/classFileParser.cpp
> +++ b/src/hotspot/share/classfile/classFileParser.cpp
> @@ -3592,6 +3592,7 @@
> this_klass->set_methods(_methods);
> this_klass->set_inner_classes(_inner_classes);
> this_klass->set_local_interfaces(_local_interfaces);
> + this_klass->set_super(const_cast<InstanceKlass*>(_super_klass));
> this_klass->set_transitive_interfaces(_transitive_interfaces);
> this_klass->set_annotations(_combined_annotations);
>
> but it crashes in vtableEntry::verify() during fastdebug build:
>
> if (!vtklass->is_subtype_of(method()->method_holder())) {
> #ifndef PRODUCT
> print();
> #endif
> fatal("vtableEntry " PTR_FORMAT ": method is from subclass",
> p2i(this)); <<<<-- crashes here
> }
>
> Here's the call stack from the hs err log:
>
> V [libjvm.so+0xb32bbe] report_fatal(char const*, int, char const*,
> ...)+0xfe
> V [libjvm.so+0x1215963] klassVtable::verify(outputStream*, bool)+0x113
> V [libjvm.so+0x1219753] klassVtable::initialize_vtable(bool,
> Thread*)+0x1293
> V [libjvm.so+0x1834b6f] Universe::reinitialize_vtable_of(Klass*,
> Thread*)+0x2f
> V [libjvm.so+0x1834c2c] Universe::reinitialize_vtable_of(Klass*,
> Thread*)+0xec
> V [libjvm.so+0x1834c2c] Universe::reinitialize_vtable_of(Klass*,
> Thread*)+0xec
> V [libjvm.so+0x1837b3f] universe_post_init()+0x1af
> V [libjvm.so+0xe99aad] init_globals()+0xed
> V [libjvm.so+0x17f8b2c] Threads::create_vm(JavaVMInitArgs*,
> bool*)+0x2cc
> V [libjvm.so+0x1018af8] JNI_CreateJavaVM+0xa8
> C [libjli.so+0x3e81] JavaMain+0x81
>
> I will send you the hs err and build logs off list.
>
> thanks,
> Calvin
>
> On 4/30/18, 2:20 PM, coleen.phillimore at oracle.com wrote:
>>
>>
>> On 4/30/18 4:58 PM, Calvin Cheung wrote:
>>> Hi Coleen,
>>>
>>> Thanks for your review.
>>>
>>> On 4/30/18, 10:23 AM, coleen.phillimore at oracle.com wrote:
>>>>
>>>> This sharing of metadata has been prone to bugs. Can you have the
>>>> same bug with the _secondary_super field?
>>>> InstanceKlass::deallocate_contents() checks:
>>>>
>>>> secondary_supers() != transitive_interfaces() &&
>>>>
>>>> and will free the field possibly from the super class if
>>>> transitive_interfaces() is still NULL. (If I understand this
>>>> correctly).
>>> If it passes the conditions check in the 'if' block, it will
>>> deallocate the _secondary_supers.
>>> It maybe fine because the crash was in visit_all_interfaces() where
>>> it doesn't dereference the _secondary_supers.
>>
>> It seems like it would deallocate _secondary_supers if an OOM
>> occurred after it's set to the super's transitive_interfaces and
>> before _transitive_interfaces is set. There could be a state that
>> could cause this to happen. I would have to trace through to see
>> what sort of crash would happen.
>>
>>>>
>>>> Wouldn't it be easier just to eagerly set the super class, and keep
>>>> the call to initialize_supers() where it is?
>>> Do you mean adding the following in
>>> ClassFileParser::apply_parsed_class_metadata() and reverting the
>>> rest of the changes?
>>>
>>> this_klass->set_super(const_cast<Klass*>(_super_klass));
>>>
>>
>> Yes, can you try this? This line with a comment would be less
>> complicated than passing NULL to initialize_supers() for the
>> arrayKlass versions.
>>
>>
>>> BTW, I think the first arg to initialize_supers() should be casted
>>> to Klass* like above because the _super_klass is already an
>>> InstanceKlass*.
>>>
>>> ik->initialize_supers(const_cast<InstanceKlass*>(_super_klass) ...
>>>
>>>
>> I think we still need some cast here and above because _super_klass
>> is defined as const, and this function and set_super are both not
>> const-safe, which is a bigger change. Or you could make
>> ClassFileParser::_super_klass not const since const is cast away.
>>
>>>>
>>>> http://cr.openjdk.java.net/~ccheung/8200466/webrev.00/src/hotspot/share/classfile/classFileParser.cpp.udiff.html
>>>>
>>>>
>>>> **** 5884,5893 *****
>>>> *--- 5889,5899 ----*
>>>> *Annotations::free_contents(_loader_data, _fields_annotations);*
>>>> *Annotations::free_contents(_loader_data, _fields_type_annotations);*
>>>> *}*
>>>> **
>>>> *clear_class_metadata();*
>>>> *+ _transitive_interfaces = NULL;*
>>>> **
>>>>
>>>> clear_class_metadata() already sets the _transitive_interfaces to
>>>> NULL, so this shouldn't be needed.
>>> The current change does not set the _trasitive_interfaces to NULL in
>>> clear_class_metadata().
>>>
>>> From the udiff above:
>>>
>>> **** 5832,5842 *****
>>> *--- 5838,5847 ----*
>>> * _cp = NULL;*
>>> * _fields = NULL;*
>>> * _methods = NULL;*
>>> * _inner_classes = NULL;*
>>> * _local_interfaces = NULL;*
>>> * _transitive_interfaces = NULL;*
>>> * _combined_annotations = NULL;*
>>> * _annotations = _type_annotations = NULL;*
>>> * _fields_annotations = _fields_type_annotations = NULL;*
>>> * }*
>>
>> Oh I see it now and why you changed it. Can you see if setting the
>> Klass::_super ahead of setting _transitive_interfaces would work better?
>>
>> thanks,
>> Coleen
>>
>>>
>>> thanks,
>>> Calvin
>>>>
>>>> thanks,
>>>> Coleen
>>>>
>>>> On 4/27/18 12:46 AM, Calvin Cheung wrote:
>>>>> JBS: https://bugs.openjdk.java.net/browse/JDK-8200466
>>>>>
>>>>> webrev: http://cr.openjdk.java.net/~ccheung/8200466/webrev.00/
>>>>>
>>>>> This bug was discovered during the investigation of JDK-8200078
>>>>> <https://bugs.openjdk.java.net/browse/JDK-8200078>.
>>>>>
>>>>> I've included the following comment in classFileParser.cpp to
>>>>> summarize the change:
>>>>>
>>>>> // 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.
>>>>>
>>>>> Testing: (on Oracle platforms)
>>>>> hs-tier{1,2,3}
>>>>> closed (soon will be open) PCL (parallel class loading) tests
>>>>>
>>>>> thanks,
>>>>> Calvin
>>>>
>>
More information about the hotspot-runtime-dev
mailing list