RFR: 8376568: Change Thread::getStackTrace to use handshake op for all cases

Alan Bateman alanb at openjdk.org
Thu Jan 29 09:15:36 UTC 2026


On Thu, 29 Jan 2026 04:30:46 GMT, David Holmes <dholmes at openjdk.org> wrote:

>> JDK-8364343 upgraded the virtual thread transition management to be independent of JVMTI. We can update java_lang_Thread::async_get_stack_trace to use it and remove the suspend + retry code from Thread.getStackTrace.
>> 
>> A summary of the changes:
>> 
>> - java_lang_Thread::async_get_stack_trace is changed to use the new handshake op so it can be called to get the stack trace of a started thread in any state
>> - Thread::getStackTrace is changed to use async_get_stack_trace for all cases
>> - The SUSPENDED substate in VirtualThread is removed
>> - JVM_CreateThreadSnapshot is changed to be usable when JVMTI is not compiled in
>> - ThreadSnapshotFactory::get_thread_snapshot is changed to not upcall to StackTraceElement to complete the init of the stack trace
>> 
>> The changes mean that Thread::getStackTrace may be slower when sampling a virtual thread in transition. This case should be rare, and it isn't really a performance critical op anyway. I prototyped use a spin loop and an increasing wait time in MountUnmountDisabler::disable_transition_for_one to avoid the wait(10) but decided to leave it out for now. Future work may examine this issue as there may be other cases (with JVMTI) that would benefit from avoiding the wait.
>> 
>> A future PR might propose to change Thread.getStackTrace to use ThreadSnapshot and allow java_lang_Thread::async_get_stack_trace be removed. This requires more extensive changes to ThreadSnapshotFactory to reduce overhead when only the stack trace is required.
>> 
>> Testing: tier1-5.  The changes has been already been tested in the loom repo for a few months.
>
> src/hotspot/share/services/threadService.cpp line 1479:
> 
>> 1477:   if (cl._thread_status == JavaThreadStatus::NEW || cl._thread_status == JavaThreadStatus::TERMINATED) {
>> 1478:     return nullptr;
>> 1479:   }
> 
> It is not obvious to me why this is only a possibility now?

ThreadSnapshot.of(Thread) may be invoked with a platform or virtual Thread in any state. It could sample the thread state before calling ThreadSnapshotFactory::get_thread_snapshot. That would allow it to filter out unstarted/NEW threads. It could also filter terminated threads but that would be racy and get_thread_snapshot would still need to handle terminated threads.

For platform threads, get_thread_snapshot will bail out early if there is no JavaThread. So the effect of the above is to have virtual threads also be filtered out.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/29461#discussion_r2740654504


More information about the core-libs-dev mailing list