RFR(S): 8200466: Revisit the setting of _transitive_interfaces in InstanceKlass

Calvin Cheung calvin.cheung at oracle.com
Tue May 1 00:24:22 UTC 2018


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