--- old/src/hotspot/share/prims/jvmtiEnvBase.cpp 2020-07-01 10:45:30.075557038 +0900 +++ new/src/hotspot/share/prims/jvmtiEnvBase.cpp 2020-07-01 10:45:29.997554929 +0900 @@ -816,13 +816,14 @@ #ifdef ASSERT uint32_t debug_bits = 0; #endif - assert((SafepointSynchronize::is_at_safepoint() || - java_thread->is_thread_fully_suspended(false, &debug_bits)), - "at safepoint or target thread is suspended"); + Thread *current_thread = Thread::current(); + assert(current_thread == java_thread || + SafepointSynchronize::is_at_safepoint() || + current_thread == java_thread->active_handshaker(), + "call by myself / at safepoint / at handshake"); int count = 0; if (java_thread->has_last_Java_frame()) { RegisterMap reg_map(java_thread); - Thread* current_thread = Thread::current(); ResourceMark rm(current_thread); javaVFrame *jvf = java_thread->last_java_vframe(®_map); HandleMark hm(current_thread); @@ -1154,8 +1155,10 @@ // Note that either or both of thr and thread_oop // may be null if the thread is new or has exited. void -VM_GetMultipleStackTraces::fill_frames(jthread jt, JavaThread *thr, oop thread_oop) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); +MultipleStackTracesCollector::fill_frames(jthread jt, JavaThread *thr, oop thread_oop) { + assert(SafepointSynchronize::is_at_safepoint() || + Thread::current() == thr->active_handshaker(), + "must be at safepoint or at direct handshake"); jint state = 0; struct StackInfoNode *node = NEW_RESOURCE_OBJ(struct StackInfoNode); @@ -1199,7 +1202,7 @@ // Based on the stack information in the linked list, allocate memory // block to return and fill it from the info in the linked list. void -VM_GetMultipleStackTraces::allocate_and_fill_stacks(jint thread_count) { +MultipleStackTracesCollector::allocate_and_fill_stacks(jint thread_count) { // do I need to worry about alignment issues? jlong alloc_size = thread_count * sizeof(jvmtiStackInfo) + _frame_count_total * sizeof(jvmtiFrameInfo); @@ -1248,14 +1251,29 @@ // only return an error from here if we didn't get a valid // thread_oop. if (thread_oop == NULL) { - set_result(err); + _collector.set_result(err); return; } // We have a valid thread_oop. } - fill_frames(jt, java_thread, thread_oop); + _collector.fill_frames(jt, java_thread, thread_oop); + } + _collector.allocate_and_fill_stacks(_thread_count); +} + +void +GetSingleStackTraceClosure::do_thread(Thread *target) { + assert(target->is_Java_thread(), "just checking"); + JavaThread *jt = (JavaThread *)target; + oop thread_oop = jt->threadObj(); + + if (!jt->is_exiting() && (thread_oop != NULL)) { + ResourceMark rm; + _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), + jt, thread_oop); + _collector.allocate_and_fill_stacks(1); + _collector.set_result(JVMTI_ERROR_NONE); } - allocate_and_fill_stacks(_thread_count); } void @@ -1272,11 +1290,11 @@ !jt->is_hidden_from_external_view()) { ++_final_thread_count; // Handle block of the calling thread is used to create local refs. - fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), - jt, thread_oop); + _collector.fill_frames((jthread)JNIHandles::make_local(_calling_thread, thread_oop), + jt, thread_oop); } } - allocate_and_fill_stacks(_final_thread_count); + _collector.allocate_and_fill_stacks(_final_thread_count); } // Verifies that the top frame is a java frame in an expected state. @@ -1528,12 +1546,11 @@ } void -VM_GetStackTrace::doit() { - _result = JVMTI_ERROR_THREAD_NOT_ALIVE; - ThreadsListHandle tlh; - if (_java_thread != NULL && tlh.includes(_java_thread) - && !_java_thread->is_exiting() && _java_thread->threadObj() != NULL) { - _result = ((JvmtiEnvBase *)_env)->get_stack_trace(_java_thread, +GetStackTraceClosure::do_thread(Thread *target) { + assert(target->is_Java_thread(), "just checking"); + JavaThread *jt = (JavaThread *)target; + if (!jt->is_exiting() && (jt->threadObj() != NULL)) { + _result = ((JvmtiEnvBase *)_env)->get_stack_trace(jt, _start_depth, _max_count, _frame_buffer, _count_ptr); }