diff -r 8ebcedb7604d -r 716c64bda5ba src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Oct 18 13:09:47 2012 -0400 +++ b/src/share/vm/runtime/thread.cpp Fri Oct 19 21:40:07 2012 -0400 @@ -323,12 +323,10 @@ os::initialize_thread(this); #if INCLUDE_NMT - // record thread's native stack, stack grows downward - if (MemTracker::is_on()) { - address stack_low_addr = stack_base() - stack_size(); - MemTracker::record_thread_stack(stack_low_addr, stack_size(), this, + // record thread's native stack, stack grows downward + address stack_low_addr = stack_base() - stack_size(); + MemTracker::record_thread_stack(stack_low_addr, stack_size(), this, CURRENT_PC); - } #endif // INCLUDE_NMT } @@ -345,6 +343,9 @@ if (_stack_base != NULL) { address low_stack_addr = stack_base() - stack_size(); MemTracker::release_thread_stack(low_stack_addr, stack_size(), this); +#ifdef ASSERT + set_stack_base(NULL); +#endif } #endif // INCLUDE_NMT @@ -1521,10 +1522,12 @@ tty->print_cr("terminate thread %p", this); } - // Info NMT that this JavaThread is exiting, its memory - // recorder should be collected + // By now, this thread should already be invisible to safepoint, + // and its per-thread recorder also collected. assert(!is_safepoint_visible(), "wrong state"); - MemTracker::thread_exiting(this); +#if INCLUDE_NMT + assert(get_recorder() == NULL, "Already collected"); +#endif // INCLUDE_NMT // JSR166 -- return the parker to the free list Parker::Release(_parker); @@ -2425,6 +2428,7 @@ } void JavaThread::remove_stack_guard_pages() { + assert(Thread::current() == this, "from different thread"); if (_stack_guard_state == stack_guard_unused) return; address low_addr = stack_base() - stack_size(); size_t len = (StackYellowPages + StackRedPages) * os::vm_page_size(); @@ -4093,7 +4097,10 @@ // Now, this thread is not visible to safepoint p->set_safepoint_visible(false); - + // once the thread becomes safepoint invisible, we can not use its per-thread + // recorder. And Threads::do_threads() no longer walks this thread, so we have + // to release its per-thread recorder here. + MemTracker::thread_exiting(p); } // unlock Threads_lock // Since Events::log uses a lock, we grab it outside the Threads_lock