8319935: Ensure only one JvmtiThreadState is created for one JavaThread associated with attached native thread

Reviewed-by: manc, dholmes, sspitsyn
This commit is contained in:
Jiangli Zhou 2023-11-29 16:05:54 +00:00
parent a2c5f1fc91
commit da7bcfcf6e
2 changed files with 24 additions and 6 deletions

View File

@ -3139,6 +3139,13 @@ bool JvmtiSampledObjectAllocEventCollector::object_alloc_is_safe_to_sample() {
return false;
}
// If the current thread is attaching from native and its Java thread object
// is being allocated, things are not ready for allocation sampling.
JavaThread* jt = JavaThread::cast(thread);
if (jt->is_attaching_via_jni() && jt->threadObj() == nullptr) {
return false;
}
if (MultiArray_lock->owner() == thread) {
return false;
}

View File

@ -78,17 +78,27 @@ inline JvmtiThreadState* JvmtiThreadState::state_for_while_locked(JavaThread *th
NoSafepointVerifier nsv; // oop is safe to use.
if (thread_oop == nullptr) { // Then thread should not be null (see assert above).
thread_oop = thread->jvmti_vthread() != nullptr ? thread->jvmti_vthread() : thread->threadObj();
}
// In a case of unmounted virtual thread the thread can be null.
JvmtiThreadState *state = thread == nullptr ? nullptr : thread->jvmti_thread_state();
if (state == nullptr && thread != nullptr && thread->is_exiting()) {
// Don't add a JvmtiThreadState to a thread that is exiting.
if (state == nullptr && thread != nullptr &&
(thread->is_exiting() || thread->is_attaching_via_jni())) {
// Don't add a JvmtiThreadState to a thread that is exiting or is attaching.
// When a thread is attaching, it may not have a Java level thread object
// created yet.
return nullptr;
}
// Make sure we don't see an incomplete state. An incomplete state can cause
// a duplicate JvmtiThreadState being created below and bound to the 'thread'
// incorrectly, which leads to stale JavaThread* from the JvmtiThreadState
// after the thread exits.
assert(state == nullptr || state->get_thread_oop() != nullptr,
"incomplete state");
if (thread_oop == nullptr) { // Then thread should not be null (see assert above).
thread_oop = thread->jvmti_vthread() != nullptr ? thread->jvmti_vthread() : thread->threadObj();
}
if (state == nullptr || state->get_thread_oop() != thread_oop) {
// Check if java_lang_Thread already has a link to the JvmtiThreadState.
if (thread_oop != nullptr) { // thread_oop can be null during early VMStart.
@ -98,6 +108,7 @@ inline JvmtiThreadState* JvmtiThreadState::state_for_while_locked(JavaThread *th
state = new JvmtiThreadState(thread, thread_oop);
}
}
assert(state != nullptr, "sanity check");
return state;
}