Skip to content

Commit 4669005

Browse files
author
David Holmes
committed
8361912: ThreadsListHandle::cv_internal_thread_to_JavaThread does not deal with a virtual thread's carrier thread
Reviewed-by: pchilanomate, dcubed, amenkov, sspitsyn
1 parent 3e4e5dd commit 4669005

File tree

4 files changed

+30
-66
lines changed

4 files changed

+30
-66
lines changed

src/hotspot/share/prims/jvmtiExport.cpp

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -865,47 +865,6 @@ JvmtiExport::cv_external_thread_to_JavaThread(ThreadsList * t_list,
865865
return JVMTI_ERROR_NONE;
866866
}
867867

868-
// Convert an oop to a JavaThread found on the specified ThreadsList.
869-
// The ThreadsListHandle in the caller "protects" the returned
870-
// JavaThread *.
871-
//
872-
// On success, *jt_pp is set to the converted JavaThread * and
873-
// JVMTI_ERROR_NONE is returned. On error, returns various
874-
// JVMTI_ERROR_* values.
875-
//
876-
jvmtiError
877-
JvmtiExport::cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
878-
JavaThread ** jt_pp) {
879-
assert(t_list != nullptr, "must have a ThreadsList");
880-
assert(thread_oop != nullptr, "must have an oop");
881-
assert(jt_pp != nullptr, "must have a return JavaThread pointer");
882-
883-
if (!thread_oop->is_a(vmClasses::Thread_klass())) {
884-
// The oop is not a java.lang.Thread.
885-
return JVMTI_ERROR_INVALID_THREAD;
886-
}
887-
// Looks like a java.lang.Thread oop at this point.
888-
889-
JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
890-
if (java_thread == nullptr) {
891-
// The java.lang.Thread does not contain a JavaThread * so it has
892-
// not yet run or it has died.
893-
return JVMTI_ERROR_THREAD_NOT_ALIVE;
894-
}
895-
// Looks like a live JavaThread at this point.
896-
897-
if (!t_list->includes(java_thread)) {
898-
// Not on the JavaThreads list so it is not alive.
899-
return JVMTI_ERROR_THREAD_NOT_ALIVE;
900-
}
901-
902-
// Return a live JavaThread that is "protected" by the
903-
// ThreadsListHandle in the caller.
904-
*jt_pp = java_thread;
905-
906-
return JVMTI_ERROR_NONE;
907-
}
908-
909868
class JvmtiClassFileLoadHookPoster : public StackObj {
910869
private:
911870
Symbol* _h_name;

src/hotspot/share/prims/jvmtiExport.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,6 @@ class JvmtiExport : public AllStatic {
454454
jthread thread,
455455
JavaThread ** jt_pp,
456456
oop * thread_oop_p);
457-
static jvmtiError cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
458-
JavaThread ** jt_pp);
459457
};
460458

461459
// Support class used by JvmtiDynamicCodeEventCollector and others. It

src/hotspot/share/runtime/threadSMR.cpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,10 +791,16 @@ ThreadsListHandle::~ThreadsListHandle() {
791791
// associated ThreadsList. This ThreadsListHandle "protects" the
792792
// returned JavaThread *.
793793
//
794+
// If the jthread resolves to a virtual thread then the JavaThread *
795+
// for its current carrier thread (if any) is returned via *jt_pp.
796+
// It is up to the caller to prevent the virtual thread from changing
797+
// its mounted status, or else account for it when acting on the carrier
798+
// JavaThread.
799+
//
794800
// If thread_oop_p is not null, then the caller wants to use the oop
795-
// after this call so the oop is returned. On success, *jt_pp is set
801+
// after this call so the oop is always returned. On success, *jt_pp is set
796802
// to the converted JavaThread * and true is returned. On error,
797-
// returns false.
803+
// returns false, and *jt_pp is unchanged.
798804
//
799805
bool ThreadsListHandle::cv_internal_thread_to_JavaThread(jobject jthread,
800806
JavaThread ** jt_pp,
@@ -818,10 +824,22 @@ bool ThreadsListHandle::cv_internal_thread_to_JavaThread(jobject jthread,
818824

819825
JavaThread *java_thread = java_lang_Thread::thread_acquire(thread_oop);
820826
if (java_thread == nullptr) {
821-
// The java.lang.Thread does not contain a JavaThread* so it has not
822-
// run enough to be put on a ThreadsList or it has exited enough to
823-
// make it past ensure_join() where the JavaThread* is cleared.
824-
return false;
827+
if (!java_lang_VirtualThread::is_instance(thread_oop)) {
828+
// The java.lang.Thread does not contain a JavaThread* so it has not
829+
// run enough to be put on a ThreadsList or it has exited enough to
830+
// make it past ensure_join() where the JavaThread* is cleared.
831+
return false;
832+
} else {
833+
// For virtual threads we need to extract the carrier's JavaThread - if any.
834+
oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_oop);
835+
if (carrier_thread != nullptr) {
836+
java_thread = java_lang_Thread::thread(carrier_thread);
837+
}
838+
if (java_thread == nullptr) {
839+
// Virtual thread was unmounted, or else carrier has now terminated.
840+
return false;
841+
}
842+
}
825843
}
826844
// Looks like a live JavaThread at this point.
827845

src/hotspot/share/runtime/threadSMR.hpp

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -45,8 +45,8 @@ class ThreadsList;
4545
// operation. It is no longer necessary to hold the Threads_lock to safely
4646
// perform an operation on a target thread.
4747
//
48-
// There are several different ways to refer to java.lang.Thread objects
49-
// so we have a few ways to get a protected JavaThread *:
48+
// There are two ways to refer to java.lang.Thread objects so we have two ways
49+
// to get a protected JavaThread*:
5050
//
5151
// JNI jobject example:
5252
// jobject jthread = ...;
@@ -69,21 +69,10 @@ class ThreadsList;
6969
// }
7070
// : // do stuff with 'jt'...
7171
//
72-
// JVM/TI oop example (this one should be very rare):
73-
// oop thread_obj = ...;
74-
// :
75-
// JavaThread *jt = nullptr;
76-
// ThreadsListHandle tlh;
77-
// jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &jt);
78-
// if (err != JVMTI_ERROR_NONE) {
79-
// return err;
80-
// }
81-
// : // do stuff with 'jt'...
82-
//
8372
// A JavaThread * that is included in the ThreadsList that is held by
8473
// a ThreadsListHandle is protected as long as the ThreadsListHandle
85-
// remains in scope. The target JavaThread * may have logically exited,
86-
// but that target JavaThread * will not be deleted until it is no
74+
// remains in scope. The target JavaThread* may have logically exited,
75+
// but that target JavaThread* will not be deleted until it is no
8776
// longer protected by a ThreadsListHandle.
8877
//
8978
// SMR Support for the Threads class.
@@ -318,7 +307,7 @@ class ThreadsListHandle : public StackObj {
318307
inline Iterator begin();
319308
inline Iterator end();
320309

321-
bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p);
310+
bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread** jt_pp, oop* thread_oop_p);
322311

323312
bool includes(JavaThread* p) {
324313
return list()->includes(p);

0 commit comments

Comments
 (0)