jvmtiError JvmtiEnvBase::get_current_contended_monitor(JavaThread *calling_thread, JavaThread *java_thread, jobject *monitor_ptr) { #ifdef ASSERT uint32_t debug_bits = 0; #endif assert((SafepointSynchronize::is_at_safepoint() || is_thread_fully_suspended(java_thread, false, &debug_bits)), "at safepoint or target thread is suspended"); oop obj = NULL; ObjectMonitor *mon = java_thread->current_waiting_monitor(); if (mon == NULL) { // thread is not doing an Object.wait() call mon = java_thread->current_pending_monitor(); if (mon != NULL) { // The thread is trying to enter() or raw_enter() an ObjectMonitor. obj = (oop)mon->object(); // If obj == NULL, then ObjectMonitor is raw which doesn't count // as contended for this API } // implied else: no contended ObjectMonitor } else { // thread is doing an Object.wait() call obj = (oop)mon->object(); assert(obj != NULL, "Object.wait() should have an object"); } if (obj == NULL) { *monitor_ptr = NULL; } else { HandleMark hm; Handle hobj(obj); *monitor_ptr = jni_reference(calling_thread, hobj); } return JVMTI_ERROR_NONE; }
void DeadlockCycle::print_on(outputStream* st) const { st->cr(); st->print_cr("Found one Java-level deadlock:"); st->print("============================="); JavaThread* currentThread; ObjectMonitor* waitingToLockMonitor; oop waitingToLockBlocker; int len = _threads->length(); for (int i = 0; i < len; i++) { currentThread = _threads->at(i); waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(); waitingToLockBlocker = currentThread->current_park_blocker(); st->cr(); st->print_cr("\"%s\":", currentThread->get_thread_name()); const char* owner_desc = ",\n which is held by"; if (waitingToLockMonitor != NULL) { st->print(" waiting to lock monitor " INTPTR_FORMAT, waitingToLockMonitor); oop obj = (oop)waitingToLockMonitor->object(); if (obj != NULL) { st->print(" (object "INTPTR_FORMAT ", a %s)", (address)obj, (instanceKlass::cast(obj->klass()))->external_name()); if (!currentThread->current_pending_monitor_is_from_java()) { owner_desc = "\n in JNI, which is held by"; } } else { // No Java object associated - a JVMTI raw monitor owner_desc = " (JVMTI raw monitor),\n which is held by"; } currentThread = Threads::owning_thread_from_monitor_owner( (address)waitingToLockMonitor->owner(), false /* no locking needed */); } else { st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)", (address)waitingToLockBlocker, (instanceKlass::cast(waitingToLockBlocker->klass()))->external_name()); assert(waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass()), "Must be an AbstractOwnableSynchronizer"); oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); currentThread = java_lang_Thread::thread(ownerObj); } st->print("%s \"%s\"", owner_desc, currentThread->get_thread_name()); } st->cr(); st->cr(); // Print stack traces bool oldJavaMonitorsInStackTrace = JavaMonitorsInStackTrace; JavaMonitorsInStackTrace = true; st->print_cr("Java stack information for the threads listed above:"); st->print_cr("==================================================="); for (int j = 0; j < len; j++) { currentThread = _threads->at(j); st->print_cr("\"%s\":", currentThread->get_thread_name()); currentThread->print_stack_on(st); } JavaMonitorsInStackTrace = oldJavaMonitorsInStackTrace; }
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC void markOopDesc::print_on(outputStream* st) const { if (is_marked()) { st->print(" marked(" INTPTR_FORMAT ")", value()); } else if (has_monitor()) { // have to check has_monitor() before is_locked() st->print(" monitor(" INTPTR_FORMAT ")=", value()); ObjectMonitor* mon = monitor(); if (mon == NULL) { st->print("NULL (this should never be seen!)"); } else { st->print("{count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", mon->count(), mon->waiters(), mon->recursions(), p2i(mon->owner())); } } else if (is_locked()) { st->print(" locked(" INTPTR_FORMAT ")->", value()); if (is_neutral()) { st->print("is_neutral"); if (has_no_hash()) { st->print(" no_hash"); } else { st->print(" hash=" INTPTR_FORMAT, hash()); } st->print(" age=%d", age()); } else if (has_bias_pattern()) { st->print("is_biased"); JavaThread* jt = biased_locker(); st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt)); } else { st->print("??"); } } else { assert(is_unlocked() || has_bias_pattern(), "just checking"); st->print("mark("); if (has_bias_pattern()) st->print("biased,"); st->print("hash %#lx,", hash()); st->print("age %d)", age()); } }
// // Fabricate heavyweight monitor information for each lightweight monitor // found in the Java VFrame. // void javaVFrame::jvmpi_fab_heavy_monitors(bool query, int* fab_index, int frame_count, GrowableArray<ObjectMonitor*>* fab_list) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); ResourceMark rm; GrowableArray<MonitorInfo*>* mons = monitors(); if (mons->is_empty()) return; bool found_first_monitor = false; for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); if (monitor->owner() == NULL) continue; // skip unowned monitor // // If we haven't found a monitor before, this is the first frame, and // the thread is blocked, then we are trying to enter this monitor. // We skip it because we have already seen it before from the monitor // cache walk. // if (!found_first_monitor && frame_count == 0) { switch (thread()->thread_state()) { case _thread_blocked: case _thread_blocked_trans: continue; } } found_first_monitor = true; markOop mark = monitor->owner()->mark(); if (mark->has_locker()) { if (!query) { // not just counting so create and store at the current element // fabricate the heavyweight monitor from lightweight info ObjectMonitor *heavy = new ObjectMonitor(); heavy->set_object(monitor->owner()); // use the owning object heavy->set_owner(thread()); // use thread instead of stack address for speed fab_list->at_put(*fab_index, heavy); } (*fab_index)++; } } }
jvmtiError JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject object, jvmtiMonitorUsage* info_ptr) { HandleMark hm; Handle hobj; bool at_safepoint = SafepointSynchronize::is_at_safepoint(); // Check arguments { oop mirror = JNIHandles::resolve_external_guard(object); NULL_CHECK(mirror, JVMTI_ERROR_INVALID_OBJECT); NULL_CHECK(info_ptr, JVMTI_ERROR_NULL_POINTER); hobj = Handle(mirror); } JavaThread *owning_thread = NULL; ObjectMonitor *mon = NULL; jvmtiMonitorUsage ret = { NULL, 0, 0, NULL, 0, NULL }; uint32_t debug_bits = 0; // first derive the object's owner and entry_count (if any) { // Revoke any biases before querying the mark word if (SafepointSynchronize::is_at_safepoint()) { BiasedLocking::revoke_at_safepoint(hobj); } else { BiasedLocking::revoke_and_rebias(hobj, false, calling_thread); } address owner = NULL; { markOop mark = hobj()->mark(); if (!mark->has_monitor()) { // this object has a lightweight monitor if (mark->has_locker()) { owner = (address)mark->locker(); // save the address of the Lock word } // implied else: no owner } else { // this object has a heavyweight monitor mon = mark->monitor(); // The owner field of a heavyweight monitor may be NULL for no // owner, a JavaThread * or it may still be the address of the // Lock word in a JavaThread's stack. A monitor can be inflated // by a non-owning JavaThread, but only the owning JavaThread // can change the owner field from the Lock word to the // JavaThread * and it may not have done that yet. owner = (address)mon->owner(); } } if (owner != NULL) { // This monitor is owned so we have to find the owning JavaThread. // Since owning_thread_from_monitor_owner() grabs a lock, GC can // move our object at this point. However, our owner value is safe // since it is either the Lock word on a stack or a JavaThread *. owning_thread = Threads::owning_thread_from_monitor_owner(owner, !at_safepoint); // Cannot assume (owning_thread != NULL) here because this function // may not have been called at a safepoint and the owning_thread // might not be suspended. if (owning_thread != NULL) { // The monitor's owner either has to be the current thread, at safepoint // or it has to be suspended. Any of these conditions will prevent both // contending and waiting threads from modifying the state of // the monitor. if (!at_safepoint && !JvmtiEnv::is_thread_fully_suspended(owning_thread, true, &debug_bits)) { // Don't worry! This return of JVMTI_ERROR_THREAD_NOT_SUSPENDED // will not make it back to the JVM/TI agent. The error code will // get intercepted in JvmtiEnv::GetObjectMonitorUsage() which // will retry the call via a VM_GetObjectMonitorUsage VM op. return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } HandleMark hm; Handle th(owning_thread->threadObj()); ret.owner = (jthread)jni_reference(calling_thread, th); } // implied else: no owner } if (owning_thread != NULL) { // monitor is owned // The recursions field of a monitor does not reflect recursions // as lightweight locks before inflating the monitor are not included. // We have to count the number of recursive monitor entries the hard way. // We pass a handle to survive any GCs along the way. ResourceMark rm; ret.entry_count = count_locked_objects(owning_thread, hobj); } // implied else: entry_count == 0 } jint nWant, nWait; if (mon != NULL) { // this object has a heavyweight monitor nWant = mon->contentions(); // # of threads contending for monitor nWait = mon->waiters(); // # of threads in Object.wait() ret.waiter_count = nWant + nWait; ret.notify_waiter_count = nWait; } else { // this object has a lightweight monitor ret.waiter_count = 0; ret.notify_waiter_count = 0; } // Allocate memory for heavyweight and lightweight monitor. jvmtiError err; err = allocate(ret.waiter_count * sizeof(jthread *), (unsigned char**)&ret.waiters); if (err != JVMTI_ERROR_NONE) { return err; } err = allocate(ret.notify_waiter_count * sizeof(jthread *), (unsigned char**)&ret.notify_waiters); if (err != JVMTI_ERROR_NONE) { deallocate((unsigned char*)ret.waiters); return err; } // now derive the rest of the fields if (mon != NULL) { // this object has a heavyweight monitor // Number of waiters may actually be less than the waiter count. // So NULL out memory so that unused memory will be NULL. memset(ret.waiters, 0, ret.waiter_count * sizeof(jthread *)); memset(ret.notify_waiters, 0, ret.notify_waiter_count * sizeof(jthread *)); if (ret.waiter_count > 0) { // we have contending and/or waiting threads HandleMark hm; if (nWant > 0) { // we have contending threads ResourceMark rm; // get_pending_threads returns only java thread so we do not need to // check for non java threads. GrowableArray<JavaThread*>* wantList = Threads::get_pending_threads( nWant, (address)mon, !at_safepoint); if (wantList->length() < nWant) { // robustness: the pending list has gotten smaller nWant = wantList->length(); } for (int i = 0; i < nWant; i++) { JavaThread *pending_thread = wantList->at(i); // If the monitor has no owner, then a non-suspended contending // thread could potentially change the state of the monitor by // entering it. The JVM/TI spec doesn't allow this. if (owning_thread == NULL && !at_safepoint & !JvmtiEnv::is_thread_fully_suspended(pending_thread, true, &debug_bits)) { if (ret.owner != NULL) { destroy_jni_reference(calling_thread, ret.owner); } for (int j = 0; j < i; j++) { destroy_jni_reference(calling_thread, ret.waiters[j]); } deallocate((unsigned char*)ret.waiters); deallocate((unsigned char*)ret.notify_waiters); return JVMTI_ERROR_THREAD_NOT_SUSPENDED; } Handle th(pending_thread->threadObj()); ret.waiters[i] = (jthread)jni_reference(calling_thread, th); } } if (nWait > 0) { // we have threads in Object.wait() int offset = nWant; // add after any contending threads ObjectWaiter *waiter = mon->first_waiter(); for (int i = 0, j = 0; i < nWait; i++) { if (waiter == NULL) { // robustness: the waiting list has gotten smaller nWait = j; break; } Thread *t = mon->thread_of_waiter(waiter); if (t != NULL && t->is_Java_thread()) { JavaThread *wjava_thread = (JavaThread *)t; // If the thread was found on the ObjectWaiter list, then // it has not been notified. This thread can't change the // state of the monitor so it doesn't need to be suspended. Handle th(wjava_thread->threadObj()); ret.waiters[offset + j] = (jthread)jni_reference(calling_thread, th); ret.notify_waiters[j++] = (jthread)jni_reference(calling_thread, th); } waiter = mon->next_waiter(waiter); } } } // Adjust count. nWant and nWait count values may be less than original. ret.waiter_count = nWant + nWait; ret.notify_waiter_count = nWait; } else { // this object has a lightweight monitor and we have nothing more // to do here because the defaults are just fine. } // we don't update return parameter unless everything worked *info_ptr = ret; return JVMTI_ERROR_NONE; }
// Save JNI local handles for any objects that this frame owns. jvmtiError JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* java_thread, javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, int stack_depth) { jvmtiError err = JVMTI_ERROR_NONE; ResourceMark rm; GrowableArray<MonitorInfo*>* mons = jvf->monitors(); if (mons->is_empty()) { return err; // this javaVFrame holds no monitors } HandleMark hm; oop wait_obj = NULL; { // save object of current wait() call (if any) for later comparison ObjectMonitor *mon = java_thread->current_waiting_monitor(); if (mon != NULL) { wait_obj = (oop)mon->object(); } } oop pending_obj = NULL; { // save object of current enter() call (if any) for later comparison ObjectMonitor *mon = java_thread->current_pending_monitor(); if (mon != NULL) { pending_obj = (oop)mon->object(); } } for (int i = 0; i < mons->length(); i++) { MonitorInfo *mi = mons->at(i); if (mi->owner_is_scalar_replaced()) continue; oop obj = mi->owner(); if (obj == NULL) { // this monitor doesn't have an owning object so skip it continue; } if (wait_obj == obj) { // the thread is waiting on this monitor so it isn't really owned continue; } if (pending_obj == obj) { // the thread is pending on this monitor so it isn't really owned continue; } if (owned_monitors_list->length() > 0) { // Our list has at least one object on it so we have to check // for recursive object locking bool found = false; for (int j = 0; j < owned_monitors_list->length(); j++) { jobject jobj = ((jvmtiMonitorStackDepthInfo*)owned_monitors_list->at(j))->monitor; oop check = JNIHandles::resolve(jobj); if (check == obj) { found = true; // we found the object break; } } if (found) { // already have this object so don't include it continue; } } // add the owning object to our list jvmtiMonitorStackDepthInfo *jmsdi; err = allocate(sizeof(jvmtiMonitorStackDepthInfo), (unsigned char **)&jmsdi); if (err != JVMTI_ERROR_NONE) { return err; } Handle hobj(obj); jmsdi->monitor = jni_reference(calling_thread, hobj); jmsdi->stack_depth = stack_depth; owned_monitors_list->append(jmsdi); } return err; }
// Save global JNI handles for any objects that this thread owns. void javaVFrame::save_lock_entries(GrowableArray<jobject>* handle_list) { ResourceMark rm; GrowableArray<MonitorInfo*>* mons = monitors(); if (mons->is_empty()) { return; // this javaVFrame holds no monitors } HandleMark hm; oop wait_obj = NULL; { // save object of current wait() call (if any) for later comparison ObjectMonitor *mon = thread()->current_waiting_monitor(); if (mon != NULL) { wait_obj = (oop)mon->object(); } } oop pending_obj = NULL; { // save object of current enter() call (if any) for later comparison ObjectMonitor *mon = thread()->current_pending_monitor(); if (mon != NULL) { pending_obj = (oop)mon->object(); } } for (int i = 0; i < mons->length(); i++) { MonitorInfo *mi = mons->at(i); oop obj = mi->owner(); if (obj == NULL) { // this monitor doesn't have an owning object so skip it continue; } if (wait_obj == obj) { // the thread is waiting on this monitor so it isn't really owned continue; } if (pending_obj == obj) { // the thread is pending on this monitor so it isn't really owned continue; } if (handle_list->length() > 0) { // Our list has at least one object on it so we have to check // for recursive object locking bool found = false; for (int j = 0; j < handle_list->length(); j++) { jobject jobj = handle_list->at(j); oop check = JNIHandles::resolve(jobj); if (check == obj) { found = true; // we found the object break; } } if (found) { // already have this object so don't include it continue; } } // add the owning object to our list Handle hobj(obj); jobject jobj = (jobject)JNIHandles::make_global(hobj); handle_list->append(jobj); } }
// Find deadlocks involving object monitors and concurrent locks if concurrent_locks is true DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) { // This code was modified from the original Threads::find_deadlocks code. int globalDfn = 0, thisDfn; ObjectMonitor* waitingToLockMonitor = NULL; oop waitingToLockBlocker = NULL; bool blocked_on_monitor = false; JavaThread *currentThread, *previousThread; int num_deadlocks = 0; for (JavaThread* p = Threads::first(); p != NULL; p = p->next()) { // Initialize the depth-first-number p->set_depth_first_number(-1); } DeadlockCycle* deadlocks = NULL; DeadlockCycle* last = NULL; DeadlockCycle* cycle = new DeadlockCycle(); for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) { if (jt->depth_first_number() >= 0) { // this thread was already visited continue; } thisDfn = globalDfn; jt->set_depth_first_number(globalDfn++); previousThread = jt; currentThread = jt; cycle->reset(); // When there is a deadlock, all the monitors involved in the dependency // cycle must be contended and heavyweight. So we only care about the // heavyweight monitor a thread is waiting to lock. waitingToLockMonitor = (ObjectMonitor*)jt->current_pending_monitor(); if (concurrent_locks) { waitingToLockBlocker = jt->current_park_blocker(); } while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) { cycle->add_thread(currentThread); if (waitingToLockMonitor != NULL) { address currentOwner = (address)waitingToLockMonitor->owner(); if (currentOwner != NULL) { currentThread = Threads::owning_thread_from_monitor_owner( currentOwner, false /* no locking needed */); if (currentThread == NULL) { // This function is called at a safepoint so the JavaThread // that owns waitingToLockMonitor should be findable, but // if it is not findable, then the previous currentThread is // blocked permanently. We record this as a deadlock. num_deadlocks++; cycle->set_deadlock(true); // add this cycle to the deadlocks list if (deadlocks == NULL) { deadlocks = cycle; } else { last->set_next(cycle); } last = cycle; cycle = new DeadlockCycle(); break; } } } else { if (concurrent_locks) { if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) { oop threadObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker); currentThread = threadObj != NULL ? java_lang_Thread::thread(threadObj) : NULL; } else { currentThread = NULL; } } } if (currentThread == NULL) { // No dependency on another thread break; } if (currentThread->depth_first_number() < 0) { // First visit to this thread currentThread->set_depth_first_number(globalDfn++); } else if (currentThread->depth_first_number() < thisDfn) { // Thread already visited, and not on a (new) cycle break; } else if (currentThread == previousThread) { // Self-loop, ignore break; } else { // We have a (new) cycle num_deadlocks++; cycle->set_deadlock(true); // add this cycle to the deadlocks list if (deadlocks == NULL) { deadlocks = cycle; } else { last->set_next(cycle); } last = cycle; cycle = new DeadlockCycle(); break; } previousThread = currentThread; waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor(); if (concurrent_locks) { waitingToLockBlocker = currentThread->current_park_blocker(); } } } delete cycle; return deadlocks; }