예제 #1
0
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());
  }
}
예제 #2
0
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;
}