RFR 8082782: vm crash on StressRedefineWithoutBytecodeCorruption fails with assert(((Metadata*)obj)->is_, valid()) failed: obj is valid

Coleen Phillimore coleen.phillimore at oracle.com
Thu Jul 23 15:52:00 UTC 2015


One comment on your one comment...

On 7/23/15 9:04 AM, Daniel D. Daugherty wrote:
> Just one thing below...
>
>
> On 7/22/15 7:25 PM, Coleen Phillimore wrote:
>>
>> Dan,
>>
>> Thank you for the quick code review.
>>
>> On 7/22/15 8:35 PM, Daniel D. Daugherty wrote:
>>> On 7/22/15 10:20 AM, Coleen Phillimore wrote:
>>>> Summary: Walk compile task for Method* to not deallocate, store 
>>>> methods in methodHandle while compile task is being created
>>>
>>> Wait... 'while compile task is being created'...
>>> You're holding these handles while the compile task
>>> is being removed... Am I confused here?
>>>
>>
>> No, you're not confused, you are right, we're getting the compile 
>> task is being taken off the compile queue.
>>>
>>>> I couldn't reproduce this or write a test with the exact timing 
>>>> needed to get this crash, but this is what the stack trace and code 
>>>> inspection tells me what happened. Reran all redefinition and 
>>>> internal tonga 'quick' tests on the change with no regression.
>>>>
>>>> open webrev at http://cr.openjdk.java.net/~coleenp/8082782.01/
>>>
>>> src/share/vm/compiler/compileBroker.hpp
>>>     No comments.
>>>
>>> src/share/vm/compiler/compileBroker.cpp
>>>     Is there a reason to have save_method and save_hot_method
>>>     defined all the way up at lines 671-672 instead of
>>>     being defined and init'ed on lines 710-711?
>>
>> The methodHandle destructor has to run after the mutexLocker 
>> destructor.   The methodHandle destructors take it off the list of 
>> Methods to mark on stack to not deallocate, but have to run after the 
>> MutexLocker destructor so it has to be declared first.
>
> Ahhh... That deserves a comment, but...
> I ran into a case before where I needed:
>
>    definition objectA;
>    definition objectB;
>
>    <other code>
>    definition ret_value = something;
>
>    return ret_value
>    <objectB destructor>
>    <objectA destructor>
>
> but I couldn't find anything in C++ that guaranteed that the
> destructors are run in the opposite order of definition.
>
> What I ended up doing was this:
>
>    definition objectA;
>    definition ret_value;
>    { // make sure objectB is destructed before objectA
>      definition objectB;
>
>      <other code>
>      ret_value = something;
>    } <objectB destructor>
>
>    return ret_value
>    <objectA destructor>
>
> You might have better luck finding such a C++ guarantee,
> but if not...

It's in the C++ standard and guaranteed.  No {} are required, especially 
for your case.  For the case I have with assignment, it could go wrong 
if the assignment operator is defined incorrectly (but I believe 
methodHandle assignment operator is correct).

http://en.cppreference.com/w/cpp/language/destructor

Coleen
>
> Dan
>
>>>
>>>     L708:   // Save method pointer across
>>>         Typo: 'pointer' -> 'pointers'
>>
>> Fixed.
>>>
>>>     So the idea of this fix is that you're holding methodHandles for
>>>     these method pointers while removing the task because removing
>>>     the task can go to a safepoint. While we're at that safepoint,
>>>     a RedefineClasses call can come along and try and access/use the
>>>     method pointers. 
>>
>> RedefineClasses will walk the previous versions of the method's 
>> holder class and determine that nothing is using the old methods, and 
>> put them on the list to deallocate the next time we unload classes.   
>> The methodHandle marks these methods as being used (on_stack) across 
>> these safepoints so they stick around.
>>
>>> If we didn't have methodHandles on them, they
>>>     could be freed by the time RedefineClasses tries to access/use
>>>     them...
>>>
>>
>> They'd be freed by the time the following code uses them (if you 
>> redefine the class and subsequently do some class unloading GC, not 
>> terribly likely but can happen in this small window and seems to have 
>> happened in this crash from the dump).  It's like a naked methodOop 
>> before permgen elimination, except it doesn't move, it gets deallocated.
>>
>> The is_valid() debugging function partially detects that something 
>> has written over this bit of the metadata. Deallocation writes 0xf5 
>> over the stuff it deallocates.
>>
>>> Do I have this right? Ouch and nice find.
>>>
>> thanks!
>>> src/share/vm/runtime/thread.cpp
>>>     No comments.
>>>
>>>
>>
>> Thank you!!
>> Coleen
>>
>>>> bug link https://bugs.openjdk.java.net/browse/JDK-8082782
>>>>
>>>> Thanks,
>>>> Coleen
>>>
>>
>



More information about the hotspot-dev mailing list