< prev index next >

test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java

Print this page
*** 22,10 ***
--- 22,11 ---
   */
  import jdk.test.lib.Asserts;
  import jdk.test.lib.Utils;
  import jdk.test.lib.process.ProcessTools;
  import jdk.test.lib.process.OutputAnalyzer;
+ import jdk.test.lib.thread.VThreadScheduler;
  
  import java.lang.reflect.Constructor;
  import java.lang.reflect.InvocationTargetException;
  import java.util.List;
  import java.util.concurrent.atomic.AtomicReference;

*** 110,11 ***
  
      public static void main(String[] args) throws Exception {
          String test = args[0];
          String[] cmdArgs = new String[] {
              "-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
!             // Grant access to ThreadBuilders$VirtualThreadBuilder
              "--add-opens=java.base/java.lang=ALL-UNNAMED",
              // Enable the JNI warning
              "-Xcheck:jni",
              "-Xlog:jni=debug",
              // Enable thread termination logging as a visual cross-check
--- 111,11 ---
  
      public static void main(String[] args) throws Exception {
          String test = args[0];
          String[] cmdArgs = new String[] {
              "-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
!             // Need to open java.lang to use VThreadScheduler.virtualThreadBuilder
              "--add-opens=java.base/java.lang=ALL-UNNAMED",
              // Enable the JNI warning
              "-Xcheck:jni",
              "-Xlog:jni=debug",
              // Enable thread termination logging as a visual cross-check

*** 197,42 ***
  
          static {
              System.loadLibrary("JNIMonitor");
          }
  
-         // This gives us a way to control the scheduler used for our virtual threads. The test
-         // only works as intended when the virtual threads run on the same carrier thread (as
-         // that carrier maintains ownership of the monitor if the virtual thread fails to unlock it).
-         // The original issue was also only discovered due to the carrier thread terminating
-         // unexpectedly, so we can force that condition too by shutting down our custom scheduler.
-         private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
-             Thread.Builder.OfVirtual builder = Thread.ofVirtual();
-             try {
-                 Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
-                 Constructor<?> ctor = clazz.getDeclaredConstructor(Executor.class);
-                 ctor.setAccessible(true);
-                 return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler);
-             } catch (InvocationTargetException e) {
-                 Throwable cause = e.getCause();
-                 if (cause instanceof RuntimeException re) {
-                     throw re;
-                 }
-                 throw new RuntimeException(e);
-             } catch (Exception e) {
-                 throw new RuntimeException(e);
-             }
-         }
- 
          static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable {
              final Object[] monitors = new Object[nThreads];
              for (int i = 0; i < nThreads; i++) {
                  monitors[i] = new Object();
              }
              final AtomicReference<Throwable> exception = new AtomicReference();
              // Ensure all our VT's operate of the same carrier, sequentially.
              ExecutorService scheduler = Executors.newSingleThreadExecutor();
!             ThreadFactory factory = virtualThreadBuilder(scheduler).factory();
              for (int i = 0 ; i < nThreads; i++) {
                  Object monitor = skipUnlock ? monitors[i] : monitors[0];
                  Thread th = factory.newThread(() -> {
                          try {
                              int res = monitorEnter(monitor);
--- 198,24 ---
  
          static {
              System.loadLibrary("JNIMonitor");
          }
  
          static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable {
              final Object[] monitors = new Object[nThreads];
              for (int i = 0; i < nThreads; i++) {
                  monitors[i] = new Object();
              }
              final AtomicReference<Throwable> exception = new AtomicReference();
              // Ensure all our VT's operate of the same carrier, sequentially.
+             // This gives us a way to control the scheduler used for our virtual threads. The test
+             // only works as intended when the virtual threads run on the same carrier thread (as
+             // that carrier maintains ownership of the monitor if the virtual thread fails to unlock it).
+             // The original issue was also only discovered due to the carrier thread terminating
+             // unexpectedly, so we can force that condition too by shutting down our custom scheduler.
              ExecutorService scheduler = Executors.newSingleThreadExecutor();
!             ThreadFactory factory = VThreadScheduler.virtualThreadBuilder(scheduler).factory();
              for (int i = 0 ; i < nThreads; i++) {
                  Object monitor = skipUnlock ? monitors[i] : monitors[0];
                  Thread th = factory.newThread(() -> {
                          try {
                              int res = monitorEnter(monitor);
< prev index next >