RFR: 8376568: Change Thread::getStackTrace to use handshake op for all cases
Alan Bateman
alanb at openjdk.org
Thu Jan 29 09:03:53 UTC 2026
On Thu, 29 Jan 2026 04:31:43 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 1509:
>
>> 1507:
>> 1508: // call static StackTraceElement[] StackTraceElement.of(StackTraceElement[] stackTrace)
>> 1509: // to properly initialize STEs.
>
> Why can this be removed?
All "finishing" is now done in ThreadSnapshort.of(Thread) for all the components (locks, blockers, ...). It previously left the finishing of the stack trace to ThreadSnapshotFactory::get_thread_snapshot, so different to Thread::getStackTrace which has always done the finish in Java code.
> src/java.base/share/classes/java/lang/Thread.java line 2218:
>
>> 2216: }
>> 2217: Object trace = getStackTrace0();
>> 2218: if (trace instanceof StackTraceElement[] stackTrace) {
>
> What can this return other than a `StackTraceElement[]` ??
It can only return a StackTraceElement[] or null. Using a type pattern seemed nicer here to avoid a null check + explicit cast.
> test/micro/org/openjdk/bench/java/lang/ThreadGetStackTraceWhenParked.java line 2:
>
>> 1: /*
>> 2: * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
>
> Are these "new" test files from the Loom repo?
Yes (and from 2025).
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/29461#discussion_r2740608688
PR Review Comment: https://git.openjdk.org/jdk/pull/29461#discussion_r2740614233
PR Review Comment: https://git.openjdk.org/jdk/pull/29461#discussion_r2740614537
More information about the core-libs-dev
mailing list