Question about GetObjectMonitorUsage() JVMTI function

David Holmes david.holmes at oracle.com
Mon Jun 15 07:26:55 UTC 2020


On 15/06/2020 4:02 pm, Yasumasa Suenaga wrote:
> Hi David,
> 
> On 2020/06/15 14:15, David Holmes wrote:
>> Hi Yasumasa,
>>
>> On 15/06/2020 2:49 pm, Yasumasa Suenaga wrote:
>>> Hi all,
>>>
>>> I wonder why JvmtiEnvBase::get_object_monitor_usage() (implementation 
>>> of GetObjectMonitorUsage()) does not perform at safepoint.
>>
>> GetObjectMonitorUsage will use a safepoint if the target is not 
>> suspended:
>>
>> jvmtiError
>> JvmtiEnv::GetObjectMonitorUsage(jobject object, jvmtiMonitorUsage* 
>> info_ptr) {
>>    JavaThread* calling_thread = JavaThread::current();
>>    jvmtiError err = get_object_monitor_usage(calling_thread, object, 
>> info_ptr);
>>    if (err == JVMTI_ERROR_THREAD_NOT_SUSPENDED) {
>>      // Some of the critical threads were not suspended. go to a 
>> safepoint and try again
>>      VM_GetObjectMonitorUsage op(this, calling_thread, object, info_ptr);
>>      VMThread::execute(&op);
>>      err = op.result();
>>    }
>>    return err;
>> } /* end GetObject */
> 
> I saw this code, so I guess there are some cases when 
> JVMTI_ERROR_THREAD_NOT_SUSPENDED is not returned from 
> get_object_monitor_usage().
> 
> 
>>> Monitor owner would be acquired from monitor object at first [1], but 
>>> it would perform concurrently.
>>> If owner thread is not suspended, the owner might be changed to 
>>> others in subsequent code.
>>>
>>> For example, the owner might release the monitor before [2].
>>
>> The expectation is that when we find an owner thread it is either 
>> suspended or not. If it is suspended then it cannot release the 
>> monitor. If it is not suspended we detect that and redo the whole 
>> query at a safepoint.
> 
> I think the owner thread might resume unfortunately after suspending check.

Yes you are right. I was thinking resuming also required a safepoint but 
it only requires the Threads_lock. So yes the code is wrong.

> JavaThread::is_ext_suspend_completed() is used to check thread state, it 
> returns `true` when the thread is sleeping [3], or when it performs in 
> native [4].

Sure but if the thread is actually suspended it can't continue execution 
in the VM or in Java code.

> 
>> This appears to be an optimisation for the assumed common case where 
>> threads are first suspended and then the monitors are queried.
> 
> I agree with this, but I could find out it from JVMTI spec - it just 
> says "Get information about the object's monitor."

Yes it was just an implementation optimisation, nothing to do with the spec.

> GetObjectMonitorUsage() might return incorrect information in some case.
> 
> It starts with finding owner thread, but the owner might be just before 
> wakeup.
> So I think it is more safe if GetObjectMonitorUsage() is called at 
> safepoint in any case.

Except we're moving away from safepoints to using Handshakes, so this 
particular operation will require that the apparent owner is 
Handshake-safe (by entering a handshake with it) before querying the 
monitor. This would still be preferable I think to always using a 
safepoint for the entire operation.

Cheers,
David
-----

> 
> Thanks,
> 
> Yasumasa
> 
> 
> [3] 
> http://hg.openjdk.java.net/jdk/jdk/file/76a17c8143d8/src/hotspot/share/runtime/thread.cpp#l671 
> 
> [4] 
> http://hg.openjdk.java.net/jdk/jdk/file/76a17c8143d8/src/hotspot/share/runtime/thread.cpp#l684 
> 
> 
> 
>> However there is still a potential bug as the thread reported as the 
>> owner may not be suspended at the time we first see it, and may 
>> release the monitor, but then it may get suspended before we call:
>>
>>   owning_thread = 
>> Threads::owning_thread_from_monitor_owner(tlh.list(), owner);
>>
>> and so we think it is still the monitor owner and proceed to query the 
>> monitor information in a racy way. This can't happen when suspension 
>> itself requires a safepoint as the current thread won't go to that 
>> safepoint during this code. However, if suspension is implemented via 
>> a direct handshake with the target thread then we have a problem.
>>
>> David
>> -----
>>
>>>
>>>
>>> Thanks,
>>>
>>> Yasumasa
>>>
>>>
>>> [1] 
>>> http://hg.openjdk.java.net/jdk/jdk/file/76a17c8143d8/src/hotspot/share/prims/jvmtiEnvBase.cpp#l973 
>>>
>>> [2] 
>>> http://hg.openjdk.java.net/jdk/jdk/file/76a17c8143d8/src/hotspot/share/prims/jvmtiEnvBase.cpp#l996 
>>>


More information about the serviceability-dev mailing list