예제 #1
0
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;
}
예제 #3
0
// 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;
}
예제 #4
0
// 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);
  }
}