invalid oops during oop_do() iteration?

Y. S. Ramakrishna y.s.ramakrishna at oracle.com
Wed Jan 19 17:59:46 UTC 2011



On 01/19/11 09:30, Tony Printezis wrote:
> Not very familiar with this code, but isn't mark_sweep_phase3 the phase 
> that adjusts the reference fields in the live objects to reflect the new 
> location of the referent *before* the objects are moved? Does this 
> explain Keith's observation?

Ah, i see what you are saying; yes, that's probably it. He'd need to
do the cache-updates earlier (during the weak oops phase), or leave
the bp's relative to the code-base rather than having to update them
each time after GC.

-- ramki

> 
> Y. S. Ramakrishna wrote:
>> Can you send a pointer to the changes that you made that led
>> to this issue? In my repo, I do not see a method_at() method
>> of JvmtiBreakpoint to try to understand what the problem is.
>>
>> I didn't understand your statement "methopdOops will always be valid and
>> refer to the same method". (methodOops that are marked by GC as reachable
>> will be kept, but if you stash methodOops in yr breakpoint structure,
>> and these are weak pointers, as i assume they want to be, these would
>> be cleared (nulled) during a post-mark weak references iteration, after
>> which class unloading is also done.)
>>
>> Not sure I understood yr problem though, so more details will help.
>> -- ramki
>>
>> On 01/19/11 07:14, Keith McGuigan wrote:
>>> Hello,
>>>
>>> In some recent changes to JVMTI breakpoint code, I added some code to 
>>> update a cache during an oop_do() iteration over of methodOop.  The 
>>> cache update involves dereferencing the methodOop's constMethodOop 
>>> and getting the address to the code in it.
>>>
>>> Essentially, I'm doing something like this:
>>>
>>> JvmtiBreakpoint::oops_do(OopClosure* f) {
>>>   for (int i = 0; i < _num_methods; ++i) {
>>>     methodOop* m = method_at(i);
>>>     f->do_oop(m);
>>>
>>>   // update the cache in case the methodOop moved
>>>    _cache[i] =  (*m)->code_base() + _bci;
>>>   }
>>> }
>>>
>>> (The actual code is in GrowableCache::oops_do() in jvmtiImpl.cpp, but 
>>> this is the general idea)
>>>
>>> Doing this assumes that the methodOops will always be valid and refer 
>>> to the same method.  Considering what I'm seeing, I think this might 
>>> be an invalid assumption.   When oops_do() is called from 
>>> PSMarkSweep::mark_sweep_phase3(), I occasionally see that the 
>>> resulting methodOop* refers to something else when I'm updating the 
>>> cache (not sure what, but it doesn't appear to be the same 
>>> methodOop).  It appears to be reset correctly in a later oops_do() 
>>> iteration.
>>>
>>> Is this expected?  And if so, is there any way for me to tell when 
>>> doing the oops_do() whether or not the resulting oops are valid?  
>>> We're seeing assertion failures and crashes in nightly testing when 
>>> the oop is not the methodOop that we expected.  I'll take a quick 
>>> hack to make it work for now if we can fix it better later.
>>>
>>> If you've got anything for me to try, IM me (or email, but IM might 
>>> be faster) and I'll give it a shot.
>>>
>>> -- 
>>> - Keith



More information about the hotspot-gc-dev mailing list