< prev index next >

src/java.base/share/classes/jdk/internal/vm/ThreadSnapshot.java

Print this page
*** 24,17 ***
--- 24,21 ---
   */
  package jdk.internal.vm;
  
  import java.util.Arrays;
  import java.util.stream.Stream;
+ import jdk.internal.access.JavaLangAccess;
+ import jdk.internal.access.SharedSecrets;
  
  /**
   * Represents a snapshot of information about a Thread.
   */
  class ThreadSnapshot {
+     private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
      private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
      private static final ThreadLock[] EMPTY_LOCKS = new ThreadLock[0];
+     private static final ThreadSnapshot NOT_ALIVE = new ThreadSnapshot();
  
      // filled by VM
      private String name;
      private int threadStatus;
      private Thread carrierThread;

*** 50,19 ***
  
      private ThreadSnapshot() {}
  
      /**
       * Take a snapshot of a Thread to get all information about the thread.
!      * Return null if a ThreadSnapshot is not created, for example if the
-      * thread has terminated.
       * @throws UnsupportedOperationException if not supported by VM
       */
      static ThreadSnapshot of(Thread thread) {
!         ThreadSnapshot snapshot = create(thread);
!         if (snapshot == null) {
!             return null; // thread terminated
          }
          if (snapshot.stackTrace == null) {
              snapshot.stackTrace = EMPTY_STACK;
          }
          if (snapshot.locks != null) {
              Arrays.stream(snapshot.locks).forEach(ThreadLock::finishInit);
--- 54,40 ---
  
      private ThreadSnapshot() {}
  
      /**
       * Take a snapshot of a Thread to get all information about the thread.
!      * Return null if the thread is not alive.
       * @throws UnsupportedOperationException if not supported by VM
       */
      static ThreadSnapshot of(Thread thread) {
!         ThreadSnapshot snapshot;
!         if (thread.isVirtual()) {
!             do {
+                 // assume unmounted
+                 snapshot = JLA.supplyIfUnmounted(thread,
+                         () -> create(thread, true),    // unmounted and alive
+                         () -> NOT_ALIVE);              // not alive
+                 if (snapshot == NOT_ALIVE) {
+                     return null;
+                 } else if (snapshot == null) {
+                     // not unmounted, retry assuming mounted
+                     snapshot = create(thread, false);
+                     if (snapshot == null) {
+                         // yield before retry
+                         Thread.yield();
+                     }
+                 }
+             } while (snapshot == null);
+         } else {
+             // platform thread
+             snapshot = create(thread, false);
+             if (snapshot == null) {
+                 return null;   // not alive
+             }
          }
+ 
          if (snapshot.stackTrace == null) {
              snapshot.stackTrace = EMPTY_STACK;
          }
          if (snapshot.locks != null) {
              Arrays.stream(snapshot.locks).forEach(ThreadLock::finishInit);

*** 217,7 ***
          ThreadBlocker(int typeOrdinal, Object obj) {
              this(lockTypeValues[typeOrdinal], obj);
          }
      }
  
!     private static native ThreadSnapshot create(Thread thread);
  }
--- 242,15 ---
          ThreadBlocker(int typeOrdinal, Object obj) {
              this(lockTypeValues[typeOrdinal], obj);
          }
      }
  
!     /**
+      * Return the snapshot of the given thread if alive. If the thread is a virtual
+      * thread this method returns the snapshot if the virtual thread is mounted. If
+      * the virtual thread is unmounted then it must be suspended.
+      * @param thread the target thread
+      * @param suspendedByCaller true if a suspended unmounted virtual thread
+      * @return the snapshot, null if not alive, null if unmounted virtual and not suspended
+      */
+     private static native ThreadSnapshot create(Thread thread, boolean suspendedByCaller);
  }
< prev index next >