mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-25 14:20:35 +00:00
8361912: ThreadsListHandle::cv_internal_thread_to_JavaThread does not deal with a virtual thread's carrier thread
Reviewed-by: pchilanomate, dcubed, amenkov, sspitsyn
This commit is contained in:
parent
3e4e5dd06f
commit
4669005123
@ -865,47 +865,6 @@ JvmtiExport::cv_external_thread_to_JavaThread(ThreadsList * t_list,
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
// Convert an oop to a JavaThread found on the specified ThreadsList.
|
||||
// The ThreadsListHandle in the caller "protects" the returned
|
||||
// JavaThread *.
|
||||
//
|
||||
// On success, *jt_pp is set to the converted JavaThread * and
|
||||
// JVMTI_ERROR_NONE is returned. On error, returns various
|
||||
// JVMTI_ERROR_* values.
|
||||
//
|
||||
jvmtiError
|
||||
JvmtiExport::cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
|
||||
JavaThread ** jt_pp) {
|
||||
assert(t_list != nullptr, "must have a ThreadsList");
|
||||
assert(thread_oop != nullptr, "must have an oop");
|
||||
assert(jt_pp != nullptr, "must have a return JavaThread pointer");
|
||||
|
||||
if (!thread_oop->is_a(vmClasses::Thread_klass())) {
|
||||
// The oop is not a java.lang.Thread.
|
||||
return JVMTI_ERROR_INVALID_THREAD;
|
||||
}
|
||||
// Looks like a java.lang.Thread oop at this point.
|
||||
|
||||
JavaThread * java_thread = java_lang_Thread::thread(thread_oop);
|
||||
if (java_thread == nullptr) {
|
||||
// The java.lang.Thread does not contain a JavaThread * so it has
|
||||
// not yet run or it has died.
|
||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
||||
}
|
||||
// Looks like a live JavaThread at this point.
|
||||
|
||||
if (!t_list->includes(java_thread)) {
|
||||
// Not on the JavaThreads list so it is not alive.
|
||||
return JVMTI_ERROR_THREAD_NOT_ALIVE;
|
||||
}
|
||||
|
||||
// Return a live JavaThread that is "protected" by the
|
||||
// ThreadsListHandle in the caller.
|
||||
*jt_pp = java_thread;
|
||||
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
class JvmtiClassFileLoadHookPoster : public StackObj {
|
||||
private:
|
||||
Symbol* _h_name;
|
||||
|
||||
@ -454,8 +454,6 @@ class JvmtiExport : public AllStatic {
|
||||
jthread thread,
|
||||
JavaThread ** jt_pp,
|
||||
oop * thread_oop_p);
|
||||
static jvmtiError cv_oop_to_JavaThread(ThreadsList * t_list, oop thread_oop,
|
||||
JavaThread ** jt_pp);
|
||||
};
|
||||
|
||||
// Support class used by JvmtiDynamicCodeEventCollector and others. It
|
||||
|
||||
@ -791,10 +791,16 @@ ThreadsListHandle::~ThreadsListHandle() {
|
||||
// associated ThreadsList. This ThreadsListHandle "protects" the
|
||||
// returned JavaThread *.
|
||||
//
|
||||
// If the jthread resolves to a virtual thread then the JavaThread *
|
||||
// for its current carrier thread (if any) is returned via *jt_pp.
|
||||
// It is up to the caller to prevent the virtual thread from changing
|
||||
// its mounted status, or else account for it when acting on the carrier
|
||||
// JavaThread.
|
||||
//
|
||||
// If thread_oop_p is not null, then the caller wants to use the oop
|
||||
// after this call so the oop is returned. On success, *jt_pp is set
|
||||
// after this call so the oop is always returned. On success, *jt_pp is set
|
||||
// to the converted JavaThread * and true is returned. On error,
|
||||
// returns false.
|
||||
// returns false, and *jt_pp is unchanged.
|
||||
//
|
||||
bool ThreadsListHandle::cv_internal_thread_to_JavaThread(jobject jthread,
|
||||
JavaThread ** jt_pp,
|
||||
@ -818,10 +824,22 @@ bool ThreadsListHandle::cv_internal_thread_to_JavaThread(jobject jthread,
|
||||
|
||||
JavaThread *java_thread = java_lang_Thread::thread_acquire(thread_oop);
|
||||
if (java_thread == nullptr) {
|
||||
// The java.lang.Thread does not contain a JavaThread* so it has not
|
||||
// run enough to be put on a ThreadsList or it has exited enough to
|
||||
// make it past ensure_join() where the JavaThread* is cleared.
|
||||
return false;
|
||||
if (!java_lang_VirtualThread::is_instance(thread_oop)) {
|
||||
// The java.lang.Thread does not contain a JavaThread* so it has not
|
||||
// run enough to be put on a ThreadsList or it has exited enough to
|
||||
// make it past ensure_join() where the JavaThread* is cleared.
|
||||
return false;
|
||||
} else {
|
||||
// For virtual threads we need to extract the carrier's JavaThread - if any.
|
||||
oop carrier_thread = java_lang_VirtualThread::carrier_thread(thread_oop);
|
||||
if (carrier_thread != nullptr) {
|
||||
java_thread = java_lang_Thread::thread(carrier_thread);
|
||||
}
|
||||
if (java_thread == nullptr) {
|
||||
// Virtual thread was unmounted, or else carrier has now terminated.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Looks like a live JavaThread at this point.
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -45,8 +45,8 @@ class ThreadsList;
|
||||
// operation. It is no longer necessary to hold the Threads_lock to safely
|
||||
// perform an operation on a target thread.
|
||||
//
|
||||
// There are several different ways to refer to java.lang.Thread objects
|
||||
// so we have a few ways to get a protected JavaThread *:
|
||||
// There are two ways to refer to java.lang.Thread objects so we have two ways
|
||||
// to get a protected JavaThread*:
|
||||
//
|
||||
// JNI jobject example:
|
||||
// jobject jthread = ...;
|
||||
@ -69,21 +69,10 @@ class ThreadsList;
|
||||
// }
|
||||
// : // do stuff with 'jt'...
|
||||
//
|
||||
// JVM/TI oop example (this one should be very rare):
|
||||
// oop thread_obj = ...;
|
||||
// :
|
||||
// JavaThread *jt = nullptr;
|
||||
// ThreadsListHandle tlh;
|
||||
// jvmtiError err = JvmtiExport::cv_oop_to_JavaThread(tlh.list(), thread_obj, &jt);
|
||||
// if (err != JVMTI_ERROR_NONE) {
|
||||
// return err;
|
||||
// }
|
||||
// : // do stuff with 'jt'...
|
||||
//
|
||||
// A JavaThread * that is included in the ThreadsList that is held by
|
||||
// a ThreadsListHandle is protected as long as the ThreadsListHandle
|
||||
// remains in scope. The target JavaThread * may have logically exited,
|
||||
// but that target JavaThread * will not be deleted until it is no
|
||||
// remains in scope. The target JavaThread* may have logically exited,
|
||||
// but that target JavaThread* will not be deleted until it is no
|
||||
// longer protected by a ThreadsListHandle.
|
||||
//
|
||||
// SMR Support for the Threads class.
|
||||
@ -318,7 +307,7 @@ public:
|
||||
inline Iterator begin();
|
||||
inline Iterator end();
|
||||
|
||||
bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p);
|
||||
bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread** jt_pp, oop* thread_oop_p);
|
||||
|
||||
bool includes(JavaThread* p) {
|
||||
return list()->includes(p);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user