提交 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) { ...@@ -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) { 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); #ifndef PRODUCT
} else if (is_entry_frame()) { oops_entry_do (f, map); // simulate GC crash here to dump java thread in error report
} else if (CodeCache::contains(pc())) { oops_code_blob_do (f, cf, map); 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 { } else {
ShouldNotReachHere(); ShouldNotReachHere();
} }
......
...@@ -2554,6 +2554,9 @@ class CommandLineFlags { ...@@ -2554,6 +2554,9 @@ class CommandLineFlags {
"Include miscellaneous runtime verifications in nmethod code; " \ "Include miscellaneous runtime verifications in nmethod code; " \
"default off because it disturbs nmethod size heuristics") \ "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 */ \ /* compilation */ \
product(bool, UseCompiler, true, \ product(bool, UseCompiler, true, \
......
...@@ -991,6 +991,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, char* thread_name, bool ...@@ -991,6 +991,7 @@ void JavaThread::allocate_threadObj(Handle thread_group, char* thread_name, bool
// uniquely named instances should derive from this. // uniquely named instances should derive from this.
NamedThread::NamedThread() : Thread() { NamedThread::NamedThread() : Thread() {
_name = NULL; _name = NULL;
_processed_thread = NULL;
} }
NamedThread::~NamedThread() { NamedThread::~NamedThread() {
...@@ -2333,6 +2334,27 @@ void JavaThread::gc_prologue() { ...@@ -2333,6 +2334,27 @@ void JavaThread::gc_prologue() {
frames_do(frame_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) { void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
// Flush deferred store-barriers, if any, associated with // Flush deferred store-barriers, if any, associated with
...@@ -2349,6 +2371,8 @@ void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) { ...@@ -2349,6 +2371,8 @@ void JavaThread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
(has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
if (has_last_Java_frame()) { if (has_last_Java_frame()) {
// Record JavaThread to GC thread
RememberProcessedThread rpt(this);
// Traverse the privileged stack // Traverse the privileged stack
if (_privileged_stack_top != NULL) { if (_privileged_stack_top != NULL) {
......
...@@ -48,7 +48,12 @@ class IdealGraphPrinter; ...@@ -48,7 +48,12 @@ class IdealGraphPrinter;
// Class hierarchy // Class hierarchy
// - Thread // - Thread
// - VMThread // - NamedThread
// - VMThread
// - ConcurrentGCThread
// - WorkerThread
// - GangWorker
// - GCTaskThread
// - JavaThread // - JavaThread
// - WatcherThread // - WatcherThread
...@@ -249,6 +254,7 @@ class Thread: public ThreadShadow { ...@@ -249,6 +254,7 @@ class Thread: public ThreadShadow {
virtual bool is_GC_task_thread() const { return false; } virtual bool is_GC_task_thread() const { return false; }
virtual bool is_Watcher_thread() const { return false; } virtual bool is_Watcher_thread() const { return false; }
virtual bool is_ConcurrentGC_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"; } virtual char* name() const { return (char*)"Unknown thread"; }
...@@ -568,12 +574,18 @@ class NamedThread: public Thread { ...@@ -568,12 +574,18 @@ class NamedThread: public Thread {
}; };
private: private:
char* _name; char* _name;
// log JavaThread being processed by oops_do
JavaThread* _processed_thread;
public: public:
NamedThread(); NamedThread();
~NamedThread(); ~NamedThread();
// May only be called once per thread. // May only be called once per thread.
void set_name(const char* format, ...); 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; } 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. // 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) ...@@ -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_pending_monitor_is_from_java, bool) \
nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \ nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \
nonstatic_field(NamedThread, _name, char*) \ nonstatic_field(NamedThread, _name, char*) \
nonstatic_field(NamedThread, _processed_thread, JavaThread*) \
nonstatic_field(JavaThread, _next, JavaThread*) \ nonstatic_field(JavaThread, _next, JavaThread*) \
nonstatic_field(JavaThread, _threadObj, oop) \ nonstatic_field(JavaThread, _threadObj, oop) \
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \
......
...@@ -204,8 +204,8 @@ void VMThread::create() { ...@@ -204,8 +204,8 @@ void VMThread::create() {
} }
VMThread::VMThread() : Thread() { VMThread::VMThread() : NamedThread() {
// nothing to do set_name("VM Thread");
} }
void VMThread::destroy() { void VMThread::destroy() {
......
...@@ -83,7 +83,7 @@ class VMOperationQueue : public CHeapObj { ...@@ -83,7 +83,7 @@ class VMOperationQueue : public CHeapObj {
// like scavenge, garbage_collect etc. // like scavenge, garbage_collect etc.
// //
class VMThread: public Thread { class VMThread: public NamedThread {
private: private:
static ThreadPriority _current_priority; static ThreadPriority _current_priority;
...@@ -101,8 +101,6 @@ class VMThread: public Thread { ...@@ -101,8 +101,6 @@ class VMThread: public Thread {
bool is_VM_thread() const { return true; } bool is_VM_thread() const { return true; }
bool is_GC_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 // The ever running loop for the VMThread
void loop(); void loop();
......
...@@ -502,6 +502,23 @@ void VMError::report(outputStream* st) { ...@@ -502,6 +502,23 @@ void VMError::report(outputStream* st) {
#endif // ZERO #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)" ) STEP(140, "(printing VM operation)" )
if (_verbose && _thread && _thread->is_VM_thread()) { if (_verbose && _thread && _thread->is_VM_thread()) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册