< prev index next >

src/hotspot/share/prims/jvmtiEnvBase.cpp

Print this page
@@ -783,10 +783,11 @@
  }
  
  jint
  JvmtiEnvBase::get_vthread_state(oop thread_oop, JavaThread* java_thread) {
    jint state = 0;
+   bool is_mon_responsible = java_lang_VirtualThread::recheckInterval(thread_oop) > 0;
    bool ext_suspended = JvmtiVTSuspender::is_vthread_suspended(thread_oop);
    jint interrupted = java_lang_Thread::interrupted(thread_oop);
  
    if (java_thread != nullptr) {
      // If virtual thread is blocked on a monitor enter the BLOCKED_ON_MONITOR_ENTER bit

@@ -795,10 +796,12 @@
      oop ct_oop = java_lang_VirtualThread::carrier_thread(thread_oop);
      jint filtered_bits = JVMTI_THREAD_STATE_SUSPENDED | JVMTI_THREAD_STATE_INTERRUPTED;
  
      // This call can trigger a safepoint, so thread_oop must not be used after it.
      state = get_thread_state_base(ct_oop, java_thread) & ~filtered_bits;
+   } else if (is_mon_responsible) {
+     state = (jint) JavaThreadStatus::BLOCKED_ON_MONITOR_ENTER;
    } else {
      int vt_state = java_lang_VirtualThread::state(thread_oop);
      state = (jint)java_lang_VirtualThread::map_state_to_thread_status(vt_state);
    }
    // Ensure the thread has not exited after retrieving suspended/interrupted values.

@@ -996,40 +999,47 @@
  
    return err;
  }
  
  jvmtiError
- JvmtiEnvBase::get_owned_monitors(JavaThread* calling_thread, JavaThread* java_thread, javaVFrame* jvf,
-                                  GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) {
+ JvmtiEnvBase::get_owned_monitors(JavaThread* calling_thread, JavaThread* carrier, javaVFrame* jvf,
+                                  GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list, oop vthread) {
    jvmtiError err = JVMTI_ERROR_NONE;
    Thread *current_thread = Thread::current();
-   assert(java_thread->is_handshake_safe_for(current_thread),
+   assert(carrier == nullptr || carrier->is_handshake_safe_for(current_thread),
           "call by myself or at handshake");
  
    int depth = 0;
    for ( ; jvf != nullptr; jvf = jvf->java_sender()) {
      if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) {  // check for stack too deep
        // Add locked objects for this frame into list.
-       err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth - 1);
+       err = get_locked_objects_in_frame(calling_thread, carrier, jvf, owned_monitors_list, depth - 1, vthread);
        if (err != JVMTI_ERROR_NONE) {
          return err;
        }
      }
    }
  
+   if (carrier == nullptr) {
+     // vthread gets pinned if monitors are acquired via jni MonitorEnter
+     // so nothing else to do for unmounted case.
+     return err;
+   }
+ 
    // Get off stack monitors. (e.g. acquired via jni MonitorEnter).
    JvmtiMonitorClosure jmc(calling_thread, owned_monitors_list, this);
-   ObjectSynchronizer::owned_monitors_iterate(&jmc, java_thread);
+   ObjectSynchronizer::owned_monitors_iterate(&jmc, carrier);
    err = jmc.error();
  
    return err;
  }
  
  // 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, jint stack_depth) {
+ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* target,
+                                  javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list,
+                                  jint stack_depth, oop vthread) {
    jvmtiError err = JVMTI_ERROR_NONE;
    Thread* current_thread = Thread::current();
    ResourceMark rm(current_thread);
    HandleMark   hm(current_thread);
  

@@ -1042,24 +1052,32 @@
    {
      // The ObjectMonitor* can't be async deflated since we are either
      // at a safepoint or the calling thread is operating on itself so
      // it cannot leave the underlying wait() call.
      // Save object of current wait() call (if any) for later comparison.
-     ObjectMonitor *mon = java_thread->current_waiting_monitor();
-     if (mon != nullptr) {
-       wait_obj = mon->object();
+     if (target != nullptr) {
+       ObjectMonitor *mon = target->current_waiting_monitor();
+       if (mon != nullptr) wait_obj = mon->object();
      }
    }
    oop pending_obj = nullptr;
    {
      // The ObjectMonitor* can't be async deflated since we are either
      // at a safepoint or the calling thread is operating on itself so
      // it cannot leave the underlying enter() call.
      // Save object of current enter() call (if any) for later comparison.
-     ObjectMonitor *mon = java_thread->current_pending_monitor();
-     if (mon != nullptr) {
-       pending_obj = mon->object();
+     if (target != nullptr) {
+       ObjectMonitor *mon = target->current_pending_monitor();
+       if (mon != nullptr) pending_obj = mon->object();
+     } else {
+       assert(vthread != nullptr, "no vthread oop");
+       oop oopCont = java_lang_VirtualThread::continuation(vthread);
+       assert(oopCont != nullptr, "vthread with no continuation");
+       stackChunkOop chunk = jdk_internal_vm_Continuation::tail(oopCont);
+       assert(chunk != nullptr, "unmounted vthread should have a chunk");
+       ObjectMonitor *mon = chunk->objectMonitor();
+       if (mon != nullptr) pending_obj = mon->object();
      }
    }
  
    for (int i = 0; i < mons->length(); i++) {
      MonitorInfo *mi = mons->at(i);

@@ -2575,22 +2593,23 @@
  VirtualThreadGetOwnedMonitorInfoClosure::do_thread(Thread *target) {
    if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) {
      _result = JVMTI_ERROR_THREAD_NOT_ALIVE;
      return;
    }
-   JavaThread* java_thread = JavaThread::cast(target);
-   Thread* cur_thread = Thread::current();
+   JavaThread* carrier = target != nullptr ? JavaThread::cast(target) : nullptr;
+   JavaThread* cur_thread = JavaThread::current();
    ResourceMark rm(cur_thread);
    HandleMark hm(cur_thread);
  
    javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(_vthread_h());
  
-   if (!java_thread->is_exiting() && java_thread->threadObj() != nullptr) {
-     _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(java_thread,
-                                                          java_thread,
+   if (carrier == nullptr || (!carrier->is_exiting() && carrier->threadObj() != nullptr)) {
+     _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(cur_thread,
+                                                          carrier,
                                                           jvf,
-                                                          _owned_monitors_list);
+                                                          _owned_monitors_list,
+                                                          _vthread_h());
    }
  }
  
  void
  VirtualThreadGetThreadClosure::do_thread(Thread *target) {

@@ -2601,20 +2620,23 @@
  }
  
  void
  VirtualThreadGetThreadStateClosure::do_thread(Thread *target) {
    assert(target->is_Java_thread(), "just checking");
+   bool is_mon_responsible = java_lang_VirtualThread::recheckInterval(_vthread_h()) > 0;
    int vthread_state = java_lang_VirtualThread::state(_vthread_h());
    oop carrier_thread_oop = java_lang_VirtualThread::carrier_thread(_vthread_h());
    jint state;
  
    if (vthread_state == java_lang_VirtualThread::RUNNING && carrier_thread_oop != nullptr) {
      state = (jint) java_lang_Thread::get_thread_status(carrier_thread_oop);
      JavaThread* java_thread = java_lang_Thread::thread(carrier_thread_oop);
      if (java_thread->is_suspended()) {
        state |= JVMTI_THREAD_STATE_SUSPENDED;
      }
+   } else if (is_mon_responsible) {
+     state = (jint) JavaThreadStatus::BLOCKED_ON_MONITOR_ENTER;
    } else {
      state = (jint) java_lang_VirtualThread::map_state_to_thread_status(vthread_state);
    }
    if (java_lang_Thread::interrupted(_vthread_h())) {
      state |= JVMTI_THREAD_STATE_INTERRUPTED;
< prev index next >