void VM_ThreadDump::doit() { ResourceMark rm; ConcurrentLocksDump concurrent_locks(true); if (_with_locked_synchronizers) { concurrent_locks.dump_at_safepoint(); } if (_num_threads == 0) { // Snapshot all live threads for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { if (jt->is_exiting() || jt->is_hidden_from_external_view()) { // skip terminating threads and hidden threads continue; } ThreadConcurrentLocks* tcl = NULL; if (_with_locked_synchronizers) { tcl = concurrent_locks.thread_concurrent_locks(jt); } ThreadSnapshot* ts = snapshot_thread(jt, tcl); _result->add_thread_snapshot(ts); } } else { // Snapshot threads in the given _threads array // A dummy snapshot is created if a thread doesn't exist for (int i = 0; i < _num_threads; i++) { instanceHandle th = _threads->at(i); if (th() == NULL) { // skip if the thread doesn't exist // Add a dummy snapshot _result->add_thread_snapshot(new ThreadSnapshot()); continue; } // Dump thread stack only if the thread is alive and not exiting // and not VM internal thread. JavaThread* jt = java_lang_Thread::thread(th()); if (jt == NULL || /* thread not alive */ jt->is_exiting() || jt->is_hidden_from_external_view()) { // add a NULL snapshot if skipped _result->add_thread_snapshot(new ThreadSnapshot()); continue; } ThreadConcurrentLocks* tcl = NULL; if (_with_locked_synchronizers) { tcl = concurrent_locks.thread_concurrent_locks(jt); } ThreadSnapshot* ts = snapshot_thread(jt, tcl); _result->add_thread_snapshot(ts); } } }
void doit() { ResourceMark rmark; // _thread != Thread::current() RegisterMap rm(_thread, false); // There can be a race condition between a VM_Operation reaching a safepoint // and the target thread exiting from Java execution. // We must recheck the last Java frame still exists. if (!_thread->is_exiting() && _thread->has_last_Java_frame()) { javaVFrame* vf = _thread->last_java_vframe(&rm); assert(vf != NULL, "must have last java frame"); Method* method = vf->method(); _method_id = method->jmethod_id(); _bci = vf->bci(); } else { // Clear current location as the target thread has no Java frames anymore. _method_id = (jmethodID)NULL; _bci = 0; } }
void FlatProfiler::record_thread_ticks() { int maxthreads, suspendedthreadcount; JavaThread** threadsList; bool interval_expired = false; if (ProfileIntervals && (FlatProfiler::received_ticks >= interval_ticks_previous + ProfileIntervalsTicks)) { interval_expired = true; interval_ticks_previous = FlatProfiler::received_ticks; } // Try not to wait for the Threads_lock if (Threads_lock->try_lock()) { { // Threads_lock scope maxthreads = Threads::number_of_threads(); threadsList = NEW_C_HEAP_ARRAY(JavaThread *, maxthreads, mtInternal); suspendedthreadcount = 0; for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) { if (tp->is_Compiler_thread()) { // Only record ticks for active compiler threads CompilerThread* cthread = (CompilerThread*)tp; if (cthread->task() != NULL) { // The compiler is active. If we need to access any of the fields // of the compiler task we should suspend the CompilerThread first. FlatProfiler::compiler_ticks += 1; continue; } } // First externally suspend all threads by marking each for // external suspension - so it will stop at its next transition // Then do a safepoint ThreadProfiler* pp = tp->get_thread_profiler(); if (pp != NULL && pp->engaged) { MutexLockerEx ml(tp->SR_lock(), Mutex::_no_safepoint_check_flag); if (!tp->is_external_suspend() && !tp->is_exiting()) { tp->set_external_suspend(); threadsList[suspendedthreadcount++] = tp; } } } Threads_lock->unlock(); }
ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread, bool include_jvmti_agent_threads, bool include_jni_attaching_threads) { assert(cur_thread == Thread::current(), "Check current thread"); int init_size = ThreadService::get_live_thread_count(); _threads_array = new GrowableArray<instanceHandle>(init_size); MutexLockerEx ml(Threads_lock); for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { // skips JavaThreads in the process of exiting // and also skips VM internal JavaThreads // Threads in _thread_new or _thread_new_trans state are included. // i.e. threads have been started but not yet running. if (jt->threadObj() == NULL || jt->is_exiting() || !java_lang_Thread::is_alive(jt->threadObj()) || jt->is_hidden_from_external_view()) { continue; } // skip agent threads if (!include_jvmti_agent_threads && jt->is_jvmti_agent_thread()) { continue; } // skip jni threads in the process of attaching if (!include_jni_attaching_threads && jt->is_attaching_via_jni()) { continue; } instanceHandle h(cur_thread, (instanceOop) jt->threadObj()); _threads_array->append(h); } }
void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { // This is if'd out because we no longer use thread suspension. // However if someone wanted to backport this to a 5.0 jvm then this // code would be important. #if 0 if (SafepointSynchronize::is_synchronizing()) { // The safepoint mechanism is trying to synchronize all the threads. // Since this can involve thread suspension, it is not safe for us // to be here. We can reduce the deadlock risk window by quickly // returning to the SIGPROF handler. However, it is still possible // for VMThread to catch us here or in the SIGPROF handler. If we // are suspended while holding a resource and another thread blocks // on that resource in the SIGPROF handler, then we will have a // three-thread deadlock (VMThread, this thread, the other thread). trace->num_frames = ticks_safepoint; // -10 return; } #endif JavaThread* thread; if (trace->env_id == NULL || (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL || thread->is_exiting()) { // bad env_id, thread has exited or thread is exiting trace->num_frames = ticks_thread_exit; // -8 return; } if (thread->in_deopt_handler()) { // thread is in the deoptimization handler so return no frames trace->num_frames = ticks_deopt; // -9 return; } assert(JavaThread::current() == thread, "AsyncGetCallTrace must be called by the current interrupted thread"); if (!JvmtiExport::should_post_class_load()) { trace->num_frames = ticks_no_class_load; // -1 return; } if (Universe::heap()->is_gc_active()) { trace->num_frames = ticks_GC_active; // -2 return; } switch (thread->thread_state()) { case _thread_new: case _thread_uninitialized: case _thread_new_trans: // We found the thread on the threads list above, but it is too // young to be useful so return that there are no Java frames. trace->num_frames = 0; break; case _thread_in_native: case _thread_in_native_trans: case _thread_blocked: case _thread_blocked_trans: case _thread_in_vm: case _thread_in_vm_trans: { frame fr; // param isInJava == false - indicate we aren't in Java code if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) { trace->num_frames = ticks_unknown_not_Java; // -3 unknown frame } else { if (!thread->has_last_Java_frame()) { trace->num_frames = 0; // No Java frames } else { trace->num_frames = ticks_not_walkable_not_Java; // -4 non walkable frame by default forte_fill_call_trace_given_top(thread, trace, depth, fr); // This assert would seem to be valid but it is not. // It would be valid if we weren't possibly racing a gc // thread. A gc thread can make a valid interpreted frame // look invalid. It's a small window but it does happen. // The assert is left here commented out as a reminder. // assert(trace->num_frames != ticks_not_walkable_not_Java, "should always be walkable"); } } } break; case _thread_in_Java: case _thread_in_Java_trans: { frame fr; // param isInJava == true - indicate we are in Java code if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) { trace->num_frames = ticks_unknown_Java; // -5 unknown frame } else { trace->num_frames = ticks_not_walkable_Java; // -6, non walkable frame by default forte_fill_call_trace_given_top(thread, trace, depth, fr); } } break; default: // Unknown thread state trace->num_frames = ticks_unknown_state; // -7 break; } }
JNIEXPORT void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { JavaThread* thread; if (trace->env_id == NULL || (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL || thread->is_exiting()) { // bad env_id, thread has exited or thread is exiting trace->num_frames = ticks_thread_exit; // -8 return; } if (thread->in_deopt_handler()) { // thread is in the deoptimization handler so return no frames trace->num_frames = ticks_deopt; // -9 return; } assert(JavaThread::current() == thread, "AsyncGetCallTrace must be called by the current interrupted thread"); if (!JvmtiExport::should_post_class_load()) { trace->num_frames = ticks_no_class_load; // -1 return; } if (Universe::heap()->is_gc_active()) { trace->num_frames = ticks_GC_active; // -2 return; } switch (thread->thread_state()) { case _thread_new: case _thread_uninitialized: case _thread_new_trans: // We found the thread on the threads list above, but it is too // young to be useful so return that there are no Java frames. trace->num_frames = 0; break; case _thread_in_native: case _thread_in_native_trans: case _thread_blocked: case _thread_blocked_trans: case _thread_in_vm: case _thread_in_vm_trans: { frame fr; // param isInJava == false - indicate we aren't in Java code if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) { trace->num_frames = ticks_unknown_not_Java; // -3 unknown frame } else { if (!thread->has_last_Java_frame()) { trace->num_frames = 0; // No Java frames } else { trace->num_frames = ticks_not_walkable_not_Java; // -4 non walkable frame by default forte_fill_call_trace_given_top(thread, trace, depth, fr); // This assert would seem to be valid but it is not. // It would be valid if we weren't possibly racing a gc // thread. A gc thread can make a valid interpreted frame // look invalid. It's a small window but it does happen. // The assert is left here commented out as a reminder. // assert(trace->num_frames != ticks_not_walkable_not_Java, "should always be walkable"); } } } break; case _thread_in_Java: case _thread_in_Java_trans: { frame fr; // param isInJava == true - indicate we are in Java code if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) { trace->num_frames = ticks_unknown_Java; // -5 unknown frame } else { trace->num_frames = ticks_not_walkable_Java; // -6, non walkable frame by default forte_fill_call_trace_given_top(thread, trace, depth, fr); } } break; default: // Unknown thread state trace->num_frames = ticks_unknown_state; // -7 break; } }