RFR: 8242428: JVMTI thread operations should use Thread-Local Handshake

David Holmes david.holmes at oracle.com
Thu Jun 25 12:48:05 UTC 2020


Hi Yasumasa,

On 25/06/2020 6:24 pm, Yasumasa Suenaga wrote:
> Hi David,
> 
> Thanks for your comment!
> 
> On 2020/06/25 14:17, David Holmes wrote:
>> Hi Yasumasa,
>>
>> Thanks for tackling this. I've had an initial look at it and have a 
>> few concerns.
>>
>> On 24/06/2020 4:50 pm, Yasumasa Suenaga wrote:
>>> Hi all,
>>>
>>> Please review this change:
>>>
>>>    JBS: https://bugs.openjdk.java.net/browse/JDK-8242428
>>>    webrev: http://cr.openjdk.java.net/~ysuenaga/JDK-8242428/webrev.00/
>>
>> Some typos:
>>
>> invaliant -> invariant
>> directry -> directly
> 
> I will fix them.
> 
> 
>>> This change replace following VM operations to direct handshake.
>>>
>>>   - VM_GetFrameCount (GetFrameCount())
>>>   - VM_GetFrameLocation (GetFrameLocation())
>>>   - VM_GetThreadListStackTraces (GetThreadListStackTrace())
>>>   - VM_GetCurrentLocation
>>
>> It would have been better to split these out into separate changes. I 
>> am finding it very hard to track through the webrev and try to compare 
>> the old safepoint based operation with the new direct handshake 
>> approach, to check they are functionally equivalent.
> 
> I will separate them as following. What do you think?
> If you are ok, I will update JBS.
> 
>   - Thread operations
>       - VM_GetThreadListStackTraces (GetThreadListStackTrace())
>       - VM_GetStackTrace(GetStackTrace())  <- I missed it to describe in 
> previous mail, sorry.
> 
>   - Frame operations
>       - VM_GetFrameCount (GetFrameCount())
>       - VM_GetFrameLocation (GetFrameLocation())
>       - VM_GetCurrentLocation
> 
> I will start to work when they are separated.

If the frame operations are each small enough that will help.

> 
>> You are not checking the return value of Handshake::execute_direct and 
>> so are missing the possibility that the target thread has terminated 
>> before you got to do the operation on it. It isn't clear to me under 
>> what other circumstances execute_direct can also return false.
> 
> I will add it. According to Handshake::execute_direct() and 
> HandshakeOperation::do_handshake(), it seems to return false if the 
> target thread has terminated as you said.

Yes, but also if the handshake is not executed - but I don't know under 
what conditions that can occur.

> 
>> You don't seem to have these checks anymore in some places:
>>
>>    && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL)
>>
>> why not?
> 
> I thought the thread which enters handshake is always alive and it has 
> threadObj.

As far as I can see we can still engage in a handshake with a thread 
after it has marked itself as exiting.

The threadObj() can only be null while a thread is attaching, which 
means it would have to checked in the general case, but for these JVM TI 
operations if we already have a jthread reference to the target thread 
then it must be beyond that point. Mind you that same logic applies to 
the existing code so ...

> I will recover their conditions.
> (I also should recover them for GetOwnedMonitorInfoClosure and 
> GetCurrentContendedMonitorClosure - I removed them in JDK-8242425)

I think so - and we need to check the return value of execute_direct to 
determine when to report JVMTI_ERROR_THREAD_NOT_ALIVE.

> 
>> It is not clear that all the code that previously could execute at a 
>> safepoint, due to being called from a VM_Operation, is still 
>> executable at a safepoint e.g. JvmtiThreadState::count_frames()
>>
>>> GetThreadListStackTrace() uses direct handshake if thread count == 1. 
>>> In other case (thread count > 1), it would be performed as VM 
>>> operation (VM_GetThreadListStackTraces).
>>
>> This introduces a large chunk of duplicated code for the frame fill in 
>> and final allocation. Can you not reuse the existing logic that does 
>> this - and in the process do away with the the use of 
>> _needs_thread_state? I really wanted to see simpler code after this 
>> conversion.
>>
>> I'm also wondering whether we can hide all this logic in the closure, 
>> as was done with the VM_Operation i.e.
>>
>> *stack_info_ptr = op.stack_info();
> 
> I will try to refactor this change.
> 
> 
>>> Caller of VM_GetCurrentLocation 
>>> (JvmtiEnvThreadState::reset_current_location()) might be called at 
>>> safepoint. So I added safepoint check in its caller.
>>
>> I could not figure out what you were referring to here.
> 
> I guess following callpath is available:
> 
> VM_GetCurrentLocation
>    JvmtiEnvThreadState::reset_current_location()
>      JvmtiEventControllerPrivate::recompute_env_thread_enabled()
>        JvmtiEventControllerPrivate::recompute_thread_enabled()
>          JvmtiEventControllerPrivate::set_frame_pop()
>            JvmtiEventController::set_frame_pop()
>              JvmtiEnvThreadState::set_frame_pop()
>                VM_SetFramePop::doit()
> 
> However, VM_SetFramePop seems not to allow nested VM operations.

It is the outer operation that has to allow nesting but 
VM_GetCurrentLocation doesn't allow it either. So if this path is 
possible then something is broken.

Cheers,
David

> 
>>> This change has been tested in serviceability/jvmti 
>>> serviceability/jdwp vmTestbase/nsk/jvmti vmTestbase/nsk/jdi 
>>> vmTestbase/ns
>>> k/jdwp.
>>
>> Just a general comment on testing for these conversions to direct 
>> handshakes. We have no control over whether the handshake gets 
>> executed in the original thread or the target thread, so for all we 
>> know all our testing could be executing only one of the cases. This 
>> concerns me but I am not yet sure what to do about it.
>>
>> Thanks,
>> David
>> -----
>>
>>> Also I tested it on submit repo, then it has execution error 
>>> (mach5-one-ysuenaga-JDK-8242428-20200624-0054-12034717) due to 
>>> dependency error. So I think it does not occur by this change.
>>>
>>>
>>> Thanks,
>>>
>>> Yasumasa


More information about the serviceability-dev mailing list