On Thu, 29 Jan 2026 04:31:43 GMT, David Holmes <[email protected]> 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