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; }
// 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); } }