# HG changeset patch # User minqi # Date 1260558589 28800 # Node ID 547f81740344bc7188c919f8e25f6178324e830e # Parent 3115100553b5fa8e4f1bec604969a37c87e3a808 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 diff -r 3115100553b5 -r 547f81740344 src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/runtime/frame.cpp Fri Dec 11 11:09:49 2009 -0800 @@ -1190,9 +1190,19 @@ 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(); } diff -r 3115100553b5 -r 547f81740344 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/runtime/globals.hpp Fri Dec 11 11:09:49 2009 -0800 @@ -2554,6 +2554,9 @@ "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, \ diff -r 3115100553b5 -r 547f81740344 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/runtime/thread.cpp Fri Dec 11 11:09:49 2009 -0800 @@ -991,6 +991,7 @@ // uniquely named instances should derive from this. NamedThread::NamedThread() : Thread() { _name = NULL; + _processed_thread = NULL; } NamedThread::~NamedThread() { @@ -2333,6 +2334,27 @@ 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 @@ (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) { diff -r 3115100553b5 -r 547f81740344 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/runtime/thread.hpp Fri Dec 11 11:09:49 2009 -0800 @@ -48,7 +48,12 @@ // Class hierarchy // - Thread -// - VMThread +// - NamedThread +// - VMThread +// - ConcurrentGCThread +// - WorkerThread +// - GangWorker +// - GCTaskThread // - JavaThread // - WatcherThread @@ -249,6 +254,7 @@ 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 @@ }; 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. diff -r 3115100553b5 -r 547f81740344 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Dec 11 11:09:49 2009 -0800 @@ -666,6 +666,7 @@ 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) \ diff -r 3115100553b5 -r 547f81740344 src/share/vm/runtime/vmThread.cpp --- a/src/share/vm/runtime/vmThread.cpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/runtime/vmThread.cpp Fri Dec 11 11:09:49 2009 -0800 @@ -204,8 +204,8 @@ } -VMThread::VMThread() : Thread() { - // nothing to do +VMThread::VMThread() : NamedThread() { + set_name("VM Thread"); } void VMThread::destroy() { diff -r 3115100553b5 -r 547f81740344 src/share/vm/runtime/vmThread.hpp --- a/src/share/vm/runtime/vmThread.hpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/runtime/vmThread.hpp Fri Dec 11 11:09:49 2009 -0800 @@ -83,7 +83,7 @@ // like scavenge, garbage_collect etc. // -class VMThread: public Thread { +class VMThread: public NamedThread { private: static ThreadPriority _current_priority; @@ -101,8 +101,6 @@ 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(); diff -r 3115100553b5 -r 547f81740344 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Wed Dec 02 20:32:27 2009 -0500 +++ b/src/share/vm/utilities/vmError.cpp Fri Dec 11 11:09:49 2009 -0800 @@ -502,6 +502,23 @@ #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()) {