Пример #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;
}
Пример #2
0
jobject *
JvmtiEnvBase::new_jobjectArray(int length, Handle *handles) {
  if (length == 0) {
    return NULL;
  }

  jobject *objArray = (jobject *) jvmtiMalloc(sizeof(jobject) * length);
  NULL_CHECK(objArray, NULL);

  for (int i=0; i<length; i++) {
    objArray[i] = jni_reference(handles[i]);
  }
  return objArray;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
0
jclass
JvmtiEnvBase::get_jni_class_non_null(Klass* k) {
  assert(k != NULL, "k != NULL");
  return (jclass)jni_reference(k->java_mirror());
}
Пример #6
0
jclass
JvmtiEnvBase::get_jni_class_non_null(klassOop k) {
  assert(k != NULL, "k != NULL");
  return (jclass)jni_reference(Klass::cast(k)->java_mirror());
}