提交 0219cd98 编写于 作者: J joeylee.lz 提交者: joeyleeeeeee97

[Wisp] Support threadMxbean in AllThreadAsWisp

Summary: Now we can use ThreadMxBean to inspect coroutine infomation.

Test Plan: Support ThreadMxBean to inspect coroutine infomation,
including getThreadInfo, dumpAllThreads,getThreadCount, getAllThreadIds.

Reviewed-by: zhengxiaolinX, yuleil, sanhongli

Issue: https://github.com/alibaba/dragonwell8/issues/132
上级 92cfe745
...@@ -1503,17 +1503,6 @@ JVM_ENTRY(jboolean, CoroutineSupport_stealCoroutine(JNIEnv* env, jclass klass, j ...@@ -1503,17 +1503,6 @@ JVM_ENTRY(jboolean, CoroutineSupport_stealCoroutine(JNIEnv* env, jclass klass, j
return true; return true;
JVM_END JVM_END
JVM_ENTRY (jobjectArray, CoroutineSupport_getCoroutineStack(JNIEnv* env, jclass klass, jlong coroPtr))
assert(EnableCoroutine, "pre-condition");
JvmtiVMObjectAllocEventCollector oam;
Coroutine* coro = (Coroutine*)coroPtr;
Handle stacktraces = ThreadService::dump_coroutine_stack_trace(coro, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, stacktraces());
JVM_END
JVM_ENTRY (void, CoroutineSupport_checkAndThrowException0(JNIEnv* env, jclass klass, jlong coroPtr)) JVM_ENTRY (void, CoroutineSupport_checkAndThrowException0(JNIEnv* env, jclass klass, jlong coroPtr))
assert(EnableCoroutine, "pre-condition"); assert(EnableCoroutine, "pre-condition");
Coroutine* coro = (Coroutine*)coroPtr; Coroutine* coro = (Coroutine*)coroPtr;
...@@ -1880,7 +1869,6 @@ JNINativeMethod coroutine_support_methods[] = { ...@@ -1880,7 +1869,6 @@ JNINativeMethod coroutine_support_methods[] = {
{CC"getNextCoroutine", CC"(J)"COR, FN_PTR(CoroutineSupport_getNextCoroutine)}, {CC"getNextCoroutine", CC"(J)"COR, FN_PTR(CoroutineSupport_getNextCoroutine)},
{CC"moveCoroutine", CC"(JJ)V", FN_PTR(CoroutineSupport_moveCoroutine)}, {CC"moveCoroutine", CC"(JJ)V", FN_PTR(CoroutineSupport_moveCoroutine)},
{CC"markThreadCoroutine", CC"(J"COBA")V", FN_PTR(CoroutineSupport_markThreadCoroutine)}, {CC"markThreadCoroutine", CC"(J"COBA")V", FN_PTR(CoroutineSupport_markThreadCoroutine)},
{CC"getCoroutineStack", CC"(J)["STE, FN_PTR(CoroutineSupport_getCoroutineStack)},
{CC"checkAndThrowException0", CC"(J)V", FN_PTR(CoroutineSupport_checkAndThrowException0)}, {CC"checkAndThrowException0", CC"(J)V", FN_PTR(CoroutineSupport_checkAndThrowException0)},
}; };
......
...@@ -4299,6 +4299,20 @@ JavaThread* Threads::find_java_thread_from_java_tid(jlong java_tid) { ...@@ -4299,6 +4299,20 @@ JavaThread* Threads::find_java_thread_from_java_tid(jlong java_tid) {
java_thread = thread; java_thread = thread;
break; break;
} }
if (EnableCoroutine) {
for (Coroutine* co = thread->coroutine_list()->next();
co != thread->coroutine_list(); co = co->next()) {
oop wtObj = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// wtObj == 0 means coroutine is cached
if (!thread->is_exiting() &&
wtObj != NULL &&
java_tid == java_lang_Thread::thread_id(wtObj)) {
co->wisp_thread()->set_threadObj(wtObj);
return co->wisp_thread();
}
}
}
} }
return java_thread; return java_thread;
} }
......
...@@ -323,6 +323,25 @@ void VM_ThreadDump::doit() { ...@@ -323,6 +323,25 @@ void VM_ThreadDump::doit() {
} }
ThreadSnapshot* ts = snapshot_thread(jt, tcl); ThreadSnapshot* ts = snapshot_thread(jt, tcl);
_result->add_thread_snapshot(ts); _result->add_thread_snapshot(ts);
if (EnableCoroutine) {
for (Coroutine* co = jt->coroutine_list()->next();
co != jt->coroutine_list(); co = co->next()) {
oop tw = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// skip exited wisp threads
if (tw == NULL) {
continue;
}
co->wisp_thread()->set_threadObj(tw);
ThreadConcurrentLocks* wtcl = NULL;
if (_with_locked_synchronizers) {
wtcl = concurrent_locks.thread_concurrent_locks(co->wisp_thread());
}
ThreadSnapshot* wts = snapshot_coroutine(co, wtcl);
_result->add_thread_snapshot(wts);
}
}
} }
} else { } else {
// Snapshot threads in the given _threads array // Snapshot threads in the given _threads array
...@@ -336,6 +355,29 @@ void VM_ThreadDump::doit() { ...@@ -336,6 +355,29 @@ void VM_ThreadDump::doit() {
continue; continue;
} }
if (EnableCoroutine) {
jlong id = java_lang_Thread::thread_id(th());
// this would traverse thread's coroutine list
JavaThread* jt = Threads::find_java_thread_from_java_tid(id);
if (jt->is_Wisp_thread()) {
Coroutine* co = ((WispThread*)jt)->coroutine();
oop tw = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// skip exited wisp threads
if (tw == NULL) {
continue;
}
co->wisp_thread()->set_threadObj(tw);
ThreadConcurrentLocks* wtcl = NULL;
if (_with_locked_synchronizers) {
wtcl = concurrent_locks.thread_concurrent_locks(co->wisp_thread());
}
ThreadSnapshot* wts = snapshot_coroutine(co, wtcl);
_result->add_thread_snapshot(wts);
return;
}
}
// Dump thread stack only if the thread is alive and not exiting // Dump thread stack only if the thread is alive and not exiting
// and not VM internal thread. // and not VM internal thread.
JavaThread* jt = java_lang_Thread::thread(th()); JavaThread* jt = java_lang_Thread::thread(th());
...@@ -363,33 +405,13 @@ ThreadSnapshot* VM_ThreadDump::snapshot_thread(JavaThread* java_thread, ThreadCo ...@@ -363,33 +405,13 @@ ThreadSnapshot* VM_ThreadDump::snapshot_thread(JavaThread* java_thread, ThreadCo
return snapshot; return snapshot;
} }
ThreadSnapshot* VM_CoroutineDump::snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl) { ThreadSnapshot* VM_ThreadDump::snapshot_coroutine(Coroutine* coro, ThreadConcurrentLocks* tcl) {
ThreadSnapshot* snapshot = new ThreadSnapshot(java_thread); ThreadSnapshot* snapshot = new ThreadSnapshot(coro->wisp_thread());
snapshot->dump_stack_at_safepoint_for_coroutine(_target); snapshot->dump_stack_at_safepoint_for_coroutine(coro, _max_depth, _with_locked_monitors);
snapshot->set_concurrent_locks(tcl); snapshot->set_concurrent_locks(tcl);
return snapshot; return snapshot;
} }
VM_CoroutineDump::VM_CoroutineDump(ThreadDumpResult* result, Coroutine *target) {
assert(EnableCoroutine, "coroutine enabled");
_result = result;
_target = target;
}
bool VM_CoroutineDump::doit_prologue() {
assert(EnableCoroutine && Thread::current()->is_Java_thread(), "just checking");
return true;
}
void VM_CoroutineDump::doit_epilogue() {}
void VM_CoroutineDump::doit() {
ResourceMark rm;
ThreadSnapshot* ts = snapshot_thread(_target->thread(), NULL);
_result->add_thread_snapshot(ts);
}
volatile bool VM_Exit::_vm_exited = false; volatile bool VM_Exit::_vm_exited = false;
Thread * VM_Exit::_shutdown_thread = NULL; Thread * VM_Exit::_shutdown_thread = NULL;
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
template(Dummy) \ template(Dummy) \
template(ThreadStop) \ template(ThreadStop) \
template(ThreadDump) \ template(ThreadDump) \
template(CoroutineDump) \
template(PrintThreads) \ template(PrintThreads) \
template(FindDeadlocks) \ template(FindDeadlocks) \
template(ForceSafepoint) \ template(ForceSafepoint) \
...@@ -361,6 +360,7 @@ class VM_ThreadDump : public VM_Operation { ...@@ -361,6 +360,7 @@ class VM_ThreadDump : public VM_Operation {
bool _with_locked_synchronizers; bool _with_locked_synchronizers;
ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl); ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl);
ThreadSnapshot* snapshot_coroutine(Coroutine* coro, ThreadConcurrentLocks* tcl);
public: public:
VM_ThreadDump(ThreadDumpResult* result, VM_ThreadDump(ThreadDumpResult* result,
...@@ -381,23 +381,6 @@ class VM_ThreadDump : public VM_Operation { ...@@ -381,23 +381,6 @@ class VM_ThreadDump : public VM_Operation {
void doit_epilogue(); void doit_epilogue();
}; };
class VM_CoroutineDump : public VM_Operation {
private:
ThreadDumpResult* _result;
Coroutine * _target;
ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl);
public:
VM_CoroutineDump(ThreadDumpResult* result, Coroutine *target);
VMOp_Type type() const { return VMOp_CoroutineDump; }
void doit();
bool doit_prologue();
void doit_epilogue();
};
class VM_Exit: public VM_Operation { class VM_Exit: public VM_Operation {
private: private:
int _exit_code; int _exit_code;
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "runtime/vmThread.hpp" #include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp" #include "runtime/vm_operations.hpp"
#include "services/threadService.hpp" #include "services/threadService.hpp"
#include "runtime/coroutine.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
...@@ -281,31 +282,6 @@ Handle ThreadService::dump_stack_traces(GrowableArray<instanceHandle>* threads, ...@@ -281,31 +282,6 @@ Handle ThreadService::dump_stack_traces(GrowableArray<instanceHandle>* threads,
return result_obj; return result_obj;
} }
// Dump stack trace of Coroutine and return StackTraceElement[].
Handle ThreadService::dump_coroutine_stack_trace(Coroutine *coro, TRAPS) {
assert(EnableCoroutine, "coroutine enabled");
ThreadDumpResult dump_result;
VM_CoroutineDump op(&dump_result, coro);
VMThread::execute(&op);
// Allocate the resulting StackTraceElement[] object
ResourceMark rm(THREAD);
assert(dump_result.num_snapshots() == 1, "must only one stacktrace");
ThreadStackTrace* stacktrace = dump_result.snapshots()->get_stack_trace();
Handle stacktrace_h;
if (stacktrace == NULL) {
// No stack trace
stacktrace_h = Handle();
} else {
// Construct an array of java/lang/StackTraceElement object
stacktrace_h = stacktrace->allocate_fill_stack_trace_element_array(CHECK_NH);
}
return stacktrace_h;
}
void ThreadService::reset_contention_count_stat(JavaThread* thread) { void ThreadService::reset_contention_count_stat(JavaThread* thread) {
ThreadStatistics* stat = thread->get_thread_stat(); ThreadStatistics* stat = thread->get_thread_stat();
...@@ -655,7 +631,7 @@ void ThreadStackTrace::add_stack_frame(javaVFrame* jvf) { ...@@ -655,7 +631,7 @@ void ThreadStackTrace::add_stack_frame(javaVFrame* jvf) {
_depth++; _depth++;
} }
void ThreadStackTrace::dump_stack_at_safepoint_for_coroutine(Coroutine *target) { void ThreadStackTrace::dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth) {
assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped"); assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped");
Coroutine::CoroutineState state = target->state(); Coroutine::CoroutineState state = target->state();
...@@ -681,12 +657,18 @@ void ThreadStackTrace::dump_stack_at_safepoint_for_coroutine(Coroutine *target) ...@@ -681,12 +657,18 @@ void ThreadStackTrace::dump_stack_at_safepoint_for_coroutine(Coroutine *target)
} }
} }
int count = 0;
while (vf) { while (vf) {
if (vf->is_java_frame()) { if (vf->is_java_frame()) {
javaVFrame* jvf = javaVFrame::cast(vf); javaVFrame* jvf = javaVFrame::cast(vf);
add_stack_frame(jvf); add_stack_frame(jvf);
count++;
} }
vf = vf->sender(); vf = vf->sender();
if (max_depth > 0 && count == max_depth) {
// Skip frames if more than maxDepth
break;
}
} }
} }
...@@ -900,9 +882,9 @@ void ThreadSnapshot::dump_stack_at_safepoint(int max_depth, bool with_locked_mon ...@@ -900,9 +882,9 @@ void ThreadSnapshot::dump_stack_at_safepoint(int max_depth, bool with_locked_mon
_stack_trace->dump_stack_at_safepoint(max_depth); _stack_trace->dump_stack_at_safepoint(max_depth);
} }
void ThreadSnapshot::dump_stack_at_safepoint_for_coroutine(Coroutine *target) { void ThreadSnapshot::dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth, bool with_locked_monitors) {
_stack_trace = new ThreadStackTrace(_thread, false); _stack_trace = new ThreadStackTrace(_thread, with_locked_monitors);
_stack_trace->dump_stack_at_safepoint_for_coroutine(target); _stack_trace->dump_stack_at_safepoint_for_coroutine(target, max_depth);
} }
...@@ -1016,6 +998,27 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread, ...@@ -1016,6 +998,27 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread,
MutexLockerEx ml(Threads_lock); MutexLockerEx ml(Threads_lock);
for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
if (!ThreadsListEnumerator::skipThread(jt, include_jvmti_agent_threads, include_jni_attaching_threads)) {
instanceHandle h(cur_thread, (instanceOop) jt->threadObj());
_threads_array->append(h);
}
if (EnableCoroutine) {
for (Coroutine* co = jt->coroutine_list()->next(); co != jt->coroutine_list(); co = co->next()) {
if (!ThreadsListEnumerator::skipThread(co->thread(), include_jvmti_agent_threads, include_jni_attaching_threads)) {
oop tw = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// skip exited wisp threads
if (tw != NULL) {
instanceHandle hc(cur_thread, (instanceOop) tw);
_threads_array->append(hc);
}
}
}
}
}
}
bool ThreadsListEnumerator::skipThread(JavaThread* jt, bool include_jvmti_agent_threads, bool include_jni_attaching_threads) {
// skips JavaThreads in the process of exiting // skips JavaThreads in the process of exiting
// and also skips VM internal JavaThreads // and also skips VM internal JavaThreads
// Threads in _thread_new or _thread_new_trans state are included. // Threads in _thread_new or _thread_new_trans state are included.
...@@ -1024,20 +1027,18 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread, ...@@ -1024,20 +1027,18 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread,
jt->is_exiting() || jt->is_exiting() ||
!java_lang_Thread::is_alive(jt->threadObj()) || !java_lang_Thread::is_alive(jt->threadObj()) ||
jt->is_hidden_from_external_view()) { jt->is_hidden_from_external_view()) {
continue; return true;
} }
// skip agent threads // skip agent threads
if (!include_jvmti_agent_threads && jt->is_jvmti_agent_thread()) { if (!include_jvmti_agent_threads && jt->is_jvmti_agent_thread()) {
continue; return true;
} }
// skip jni threads in the process of attaching // skip jni threads in the process of attaching
if (!include_jni_attaching_threads && jt->is_attaching_via_jni()) { if (!include_jni_attaching_threads && jt->is_attaching_via_jni()) {
continue; return true;
} }
instanceHandle h(cur_thread, (instanceOop) jt->threadObj()); return false;
_threads_array->append(h);
}
} }
...@@ -105,8 +105,6 @@ public: ...@@ -105,8 +105,6 @@ public:
static Handle dump_stack_traces(GrowableArray<instanceHandle>* threads, static Handle dump_stack_traces(GrowableArray<instanceHandle>* threads,
int num_threads, TRAPS); int num_threads, TRAPS);
static Handle dump_coroutine_stack_trace(Coroutine *coro, TRAPS);
static void reset_peak_thread_count(); static void reset_peak_thread_count();
static void reset_contention_count_stat(JavaThread* thread); static void reset_contention_count_stat(JavaThread* thread);
static void reset_contention_time_stat(JavaThread* thread); static void reset_contention_time_stat(JavaThread* thread);
...@@ -243,7 +241,7 @@ public: ...@@ -243,7 +241,7 @@ public:
ThreadConcurrentLocks* get_concurrent_locks() { return _concurrent_locks; } ThreadConcurrentLocks* get_concurrent_locks() { return _concurrent_locks; }
void dump_stack_at_safepoint(int max_depth, bool with_locked_monitors); void dump_stack_at_safepoint(int max_depth, bool with_locked_monitors);
void dump_stack_at_safepoint_for_coroutine(Coroutine *target); void dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth, bool with_locked_monitors);
void set_concurrent_locks(ThreadConcurrentLocks* l) { _concurrent_locks = l; } void set_concurrent_locks(ThreadConcurrentLocks* l) { _concurrent_locks = l; }
void oops_do(OopClosure* f); void oops_do(OopClosure* f);
void metadata_do(void f(Metadata*)); void metadata_do(void f(Metadata*));
...@@ -268,7 +266,7 @@ class ThreadStackTrace : public CHeapObj<mtInternal> { ...@@ -268,7 +266,7 @@ class ThreadStackTrace : public CHeapObj<mtInternal> {
void add_stack_frame(javaVFrame* jvf); void add_stack_frame(javaVFrame* jvf);
void dump_stack_at_safepoint(int max_depth); void dump_stack_at_safepoint(int max_depth);
void dump_stack_at_safepoint_for_coroutine(Coroutine *target); void dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth);
Handle allocate_fill_stack_trace_element_array(TRAPS); Handle allocate_fill_stack_trace_element_array(TRAPS);
void oops_do(OopClosure* f); void oops_do(OopClosure* f);
void metadata_do(void f(Metadata*)); void metadata_do(void f(Metadata*));
...@@ -392,6 +390,7 @@ class DeadlockCycle : public CHeapObj<mtInternal> { ...@@ -392,6 +390,7 @@ class DeadlockCycle : public CHeapObj<mtInternal> {
class ThreadsListEnumerator : public StackObj { class ThreadsListEnumerator : public StackObj {
private: private:
GrowableArray<instanceHandle>* _threads_array; GrowableArray<instanceHandle>* _threads_array;
static bool skipThread(JavaThread* jt, bool include_jvmti_agent_threads, bool include_jni_attaching_threads);
public: public:
ThreadsListEnumerator(Thread* cur_thread, ThreadsListEnumerator(Thread* cur_thread,
bool include_jvmti_agent_threads = false, bool include_jvmti_agent_threads = false,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册