Thu, 19 Jul 2012 09:05:42 -0400
7182543: NMT ON: Aggregate a few NMT related bugs
Summary: 1) Fixed MemTrackWorker::generations_in_used() calculation 2) Ensured NMT not to leak memory recorders after shutdown 3) Used ThreadCritical to block safepoint safe threads
Reviewed-by: acorn, coleenp, dholmes, kvn
1.1 --- a/src/share/vm/services/memRecorder.cpp Wed Jul 04 15:55:45 2012 -0400 1.2 +++ b/src/share/vm/services/memRecorder.cpp Thu Jul 19 09:05:42 2012 -0400 1.3 @@ -45,11 +45,11 @@ 1.4 } 1.5 1.6 1.7 -debug_only(volatile jint MemRecorder::_instance_count = 0;) 1.8 +volatile jint MemRecorder::_instance_count = 0; 1.9 1.10 MemRecorder::MemRecorder() { 1.11 assert(MemTracker::is_on(), "Native memory tracking is off"); 1.12 - debug_only(Atomic::inc(&_instance_count);) 1.13 + Atomic::inc(&_instance_count); 1.14 debug_only(set_generation();) 1.15 1.16 if (MemTracker::track_callsite()) { 1.17 @@ -83,9 +83,7 @@ 1.18 delete _next; 1.19 } 1.20 1.21 -#ifdef ASSERT 1.22 Atomic::dec(&_instance_count); 1.23 -#endif 1.24 } 1.25 1.26 // Sorting order:
2.1 --- a/src/share/vm/services/memRecorder.hpp Wed Jul 04 15:55:45 2012 -0400 2.2 +++ b/src/share/vm/services/memRecorder.hpp Thu Jul 19 09:05:42 2012 -0400 2.3 @@ -249,9 +249,9 @@ 2.4 2.5 SequencedRecordIterator pointer_itr(); 2.6 2.7 - public: 2.8 + protected: 2.9 // number of MemRecorder instance 2.10 - debug_only(static volatile jint _instance_count;) 2.11 + static volatile jint _instance_count; 2.12 2.13 private: 2.14 // sorting function, sort records into following order
3.1 --- a/src/share/vm/services/memTrackWorker.hpp Wed Jul 04 15:55:45 2012 -0400 3.2 +++ b/src/share/vm/services/memTrackWorker.hpp Thu Jul 19 09:05:42 2012 -0400 3.3 @@ -67,7 +67,7 @@ 3.4 NOT_PRODUCT(int _last_gen_in_use;) 3.5 3.6 inline int generations_in_use() const { 3.7 - return (_tail <= _head ? (_head - _tail + 1) : (MAX_GENERATIONS - (_tail - _head) + 1)); 3.8 + return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); 3.9 } 3.10 }; 3.11
4.1 --- a/src/share/vm/services/memTracker.cpp Wed Jul 04 15:55:45 2012 -0400 4.2 +++ b/src/share/vm/services/memTracker.cpp Thu Jul 19 09:05:42 2012 -0400 4.3 @@ -351,21 +351,17 @@ 4.4 } 4.5 4.6 if (thread != NULL) { 4.7 -#ifdef ASSERT 4.8 - // cause assertion on stack base. This ensures that threads call 4.9 - // Thread::record_stack_base_and_size() method, which will create 4.10 - // thread native stack records. 4.11 - thread->stack_base(); 4.12 -#endif 4.13 - // for a JavaThread, if it is running in native state, we need to transition it to 4.14 - // VM state, so it can stop at safepoint. JavaThread running in VM state does not 4.15 - // need lock to write records. 4.16 if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) { 4.17 - if (((JavaThread*)thread)->thread_state() == _thread_in_native) { 4.18 - ThreadInVMfromNative trans((JavaThread*)thread); 4.19 - create_record_in_recorder(addr, flags, size, pc, thread); 4.20 + JavaThread* java_thread = static_cast<JavaThread*>(thread); 4.21 + JavaThreadState state = java_thread->thread_state(); 4.22 + if (SafepointSynchronize::safepoint_safe(java_thread, state)) { 4.23 + // JavaThreads that are safepoint safe, can run through safepoint, 4.24 + // so ThreadCritical is needed to ensure no threads at safepoint create 4.25 + // new records while the records are being gathered and the sequence number is changing 4.26 + ThreadCritical tc; 4.27 + create_record_in_recorder(addr, flags, size, pc, java_thread); 4.28 } else { 4.29 - create_record_in_recorder(addr, flags, size, pc, thread); 4.30 + create_record_in_recorder(addr, flags, size, pc, java_thread); 4.31 } 4.32 } else { 4.33 // other threads, such as worker and watcher threads, etc. need to 4.34 @@ -390,10 +386,9 @@ 4.35 // write a record to proper recorder. No lock can be taken from this method 4.36 // down. 4.37 void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags, 4.38 - size_t size, address pc, Thread* thread) { 4.39 - assert(thread == NULL || thread->is_Java_thread(), "wrong thread"); 4.40 + size_t size, address pc, JavaThread* thread) { 4.41 4.42 - MemRecorder* rc = get_thread_recorder((JavaThread*)thread); 4.43 + MemRecorder* rc = get_thread_recorder(thread); 4.44 if (rc != NULL) { 4.45 rc->record(addr, flags, size, pc); 4.46 } 4.47 @@ -460,17 +455,18 @@ 4.48 } 4.49 } 4.50 _sync_point_skip_count = 0; 4.51 - // walk all JavaThreads to collect recorders 4.52 - SyncThreadRecorderClosure stc; 4.53 - Threads::threads_do(&stc); 4.54 - 4.55 - _thread_count = stc.get_thread_count(); 4.56 - MemRecorder* pending_recorders = get_pending_recorders(); 4.57 - 4.58 { 4.59 // This method is running at safepoint, with ThreadCritical lock, 4.60 // it should guarantee that NMT is fully sync-ed. 4.61 ThreadCritical tc; 4.62 + 4.63 + // walk all JavaThreads to collect recorders 4.64 + SyncThreadRecorderClosure stc; 4.65 + Threads::threads_do(&stc); 4.66 + 4.67 + _thread_count = stc.get_thread_count(); 4.68 + MemRecorder* pending_recorders = get_pending_recorders(); 4.69 + 4.70 if (_global_recorder != NULL) { 4.71 _global_recorder->set_next(pending_recorders); 4.72 pending_recorders = _global_recorder; 4.73 @@ -486,8 +482,6 @@ 4.74 4.75 // now, it is the time to shut whole things off 4.76 if (_state == NMT_final_shutdown) { 4.77 - _tracking_level = NMT_off; 4.78 - 4.79 // walk all JavaThreads to delete all recorders 4.80 SyncThreadRecorderClosure stc; 4.81 Threads::threads_do(&stc); 4.82 @@ -499,8 +493,16 @@ 4.83 _global_recorder = NULL; 4.84 } 4.85 } 4.86 - 4.87 - _state = NMT_shutdown; 4.88 + MemRecorder* pending_recorders = get_pending_recorders(); 4.89 + if (pending_recorders != NULL) { 4.90 + delete pending_recorders; 4.91 + } 4.92 + // try at a later sync point to ensure MemRecorder instance drops to zero to 4.93 + // completely shutdown NMT 4.94 + if (MemRecorder::_instance_count == 0) { 4.95 + _state = NMT_shutdown; 4.96 + _tracking_level = NMT_off; 4.97 + } 4.98 } 4.99 } 4.100
5.1 --- a/src/share/vm/services/memTracker.hpp Wed Jul 04 15:55:45 2012 -0400 5.2 +++ b/src/share/vm/services/memTracker.hpp Thu Jul 19 09:05:42 2012 -0400 5.3 @@ -326,7 +326,7 @@ 5.4 static void create_memory_record(address addr, MEMFLAGS type, 5.5 size_t size, address pc, Thread* thread); 5.6 static void create_record_in_recorder(address addr, MEMFLAGS type, 5.7 - size_t size, address pc, Thread* thread); 5.8 + size_t size, address pc, JavaThread* thread); 5.9 5.10 private: 5.11 // global memory snapshot