提交 9d885a3d 编写于 作者: M minqi

6361589: Print out stack trace for target thread of GC crash

Summary: If GC crashed with java thread involved, print out the java stack trace in error report
Reviewed-by: never, ysr, coleenp, dholmes
上级 0c2d2919
......@@ -1190,9 +1190,19 @@ void frame::oops_entry_do(OopClosure* f, const RegisterMap* map) {
void frame::oops_do_internal(OopClosure* f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) {
if (is_interpreted_frame()) { oops_interpreted_do(f, map, use_interpreter_oop_map_cache);
} else if (is_entry_frame()) { oops_entry_do (f, map);
} else if (CodeCache::contains(pc())) { oops_code_blob_do (f, cf, map);
#ifndef PRODUCT
// simulate GC crash here to dump java thread in error report
if (CrashGCForDumpingJavaThread) {
char *t = NULL;
*t = 'c';
}
#endif
if (is_interpreted_frame()) {
oops_interpreted_do(f, map, use_interpreter_oop_map_cache);
} else if (is_entry_frame()) {
oops_entry_do(f, map);
} else if (CodeCache::contains(pc())) {
oops_code_blob_do(f, cf, map);
} else {
ShouldNotReachHere();
}
......
......@@ -2554,6 +2554,9 @@ class CommandLineFlags {
"Include miscellaneous runtime verifications in nmethod code; " \
"default off because it disturbs nmethod size heuristics") \
\
notproduct(bool, CrashGCForDumpingJavaThread, false, \
"Manually make GC thread crash then dump java stack trace; " \
"Test only") \
\
/* compilation */ \
product(bool, UseCompiler, true, \
......
......@@ -991,6 +991,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, char* thread_name, bool
// uniquely named instances should derive from this.
NamedThread::NamedThread() : Thread() {
_name = NULL;
_processed_thread = NULL;
}
NamedThread::~NamedThread() {
......@@ -2333,6 +2334,27 @@ void JavaThread::gc_prologue() {
frames_do(frame_gc_prologue);
}
// If the caller is a NamedThread, then remember, in the current scope,
// the given JavaThread in its _processed_thread field.
class RememberProcessedThread: public StackObj {
NamedThread* _cur_thr;
public:
RememberProcessedThread(JavaThread* jthr) {
Thread* thread = Thread::current();
if (thread->is_Named_thread()) {
_cur_thr = (NamedThread *)thread;
_cur_thr->set_processed_thread(jthr);
} else {
_cur_thr = NULL;
}
}
~RememberProcessedThread() {
if (_cur_thr) {
_cur_thr->set_processed_thread(NULL);
}
}
};
void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
// Flush deferred store-barriers, if any, associated with
......@@ -2349,6 +2371,8 @@ void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
(has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
if (has_last_Java_frame()) {
// Record JavaThread to GC thread
RememberProcessedThread rpt(this);
// Traverse the privileged stack
if (_privileged_stack_top != NULL) {
......
......@@ -48,7 +48,12 @@ class IdealGraphPrinter;
// Class hierarchy
// - Thread
// - NamedThread
// - VMThread
// - ConcurrentGCThread
// - WorkerThread
// - GangWorker
// - GCTaskThread
// - JavaThread
// - WatcherThread
......@@ -249,6 +254,7 @@ class Thread: public ThreadShadow {
virtual bool is_GC_task_thread() const { return false; }
virtual bool is_Watcher_thread() const { return false; }
virtual bool is_ConcurrentGC_thread() const { return false; }
virtual bool is_Named_thread() const { return false; }
virtual char* name() const { return (char*)"Unknown thread"; }
......@@ -568,12 +574,18 @@ class NamedThread: public Thread {
};
private:
char* _name;
// log JavaThread being processed by oops_do
JavaThread* _processed_thread;
public:
NamedThread();
~NamedThread();
// May only be called once per thread.
void set_name(const char* format, ...);
virtual bool is_Named_thread() const { return true; }
virtual char* name() const { return _name == NULL ? (char*)"Unknown Thread" : _name; }
JavaThread *processed_thread() { return _processed_thread; }
void set_processed_thread(JavaThread *thread) { _processed_thread = thread; }
};
// Worker threads are named and have an id of an assigned work.
......
......@@ -666,6 +666,7 @@ static inline uint64_t cast_uint64_t(size_t x)
nonstatic_field(Thread, _current_pending_monitor_is_from_java, bool) \
nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \
nonstatic_field(NamedThread, _name, char*) \
nonstatic_field(NamedThread, _processed_thread, JavaThread*) \
nonstatic_field(JavaThread, _next, JavaThread*) \
nonstatic_field(JavaThread, _threadObj, oop) \
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \
......
......@@ -204,8 +204,8 @@ void VMThread::create() {
}
VMThread::VMThread() : Thread() {
// nothing to do
VMThread::VMThread() : NamedThread() {
set_name("VM Thread");
}
void VMThread::destroy() {
......
......@@ -83,7 +83,7 @@ class VMOperationQueue : public CHeapObj {
// like scavenge, garbage_collect etc.
//
class VMThread: public Thread {
class VMThread: public NamedThread {
private:
static ThreadPriority _current_priority;
......@@ -101,8 +101,6 @@ class VMThread: public Thread {
bool is_VM_thread() const { return true; }
bool is_GC_thread() const { return true; }
char* name() const { return (char*)"VM Thread"; }
// The ever running loop for the VMThread
void loop();
......
......@@ -502,6 +502,23 @@ void VMError::report(outputStream* st) {
#endif // ZERO
}
STEP(135, "(printing target Java thread stack)" )
// printing Java thread stack trace if it is involved in GC crash
if (_verbose && (_thread->is_Named_thread())) {
JavaThread* jt = ((NamedThread *)_thread)->processed_thread();
if (jt != NULL) {
st->print_cr("JavaThread " PTR_FORMAT " (nid = " UINTX_FORMAT ") was being processed", jt, jt->osthread()->thread_id());
if (jt->has_last_Java_frame()) {
st->print_cr("Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)");
for(StackFrameStream sfs(jt); !sfs.is_done(); sfs.next()) {
sfs.current()->print_on_error(st, buf, sizeof(buf), true);
st->cr();
}
}
}
}
STEP(140, "(printing VM operation)" )
if (_verbose && _thread && _thread->is_VM_thread()) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册