< prev index next >

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

Print this page

102  * @summary Don't do the unlock and exit by throwing, by multiple threads
103  * @library /test/lib
104  * @modules java.base/java.lang:+open
105  * @requires vm.continuations
106  * @run driver JNIMonitor MultiMissingUnlockWithThrow
107  */
108 
109 public class JNIMonitor {
110 
111     public static void main(String[] args) throws Exception {
112         String test = args[0];
113         String[] cmdArgs = new String[] {
114             "-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
115             // Grant access to ThreadBuilders$VirtualThreadBuilder
116             "--add-opens=java.base/java.lang=ALL-UNNAMED",
117             // Enable the JNI warning
118             "-Xcheck:jni",
119             "-Xlog:jni=debug",
120             // Enable thread termination logging as a visual cross-check
121             "-Xlog:thread+os=info",


122             "JNIMonitor$" + test,
123         };
124         OutputAnalyzer oa = ProcessTools.executeTestJava(cmdArgs);
125         oa.shouldHaveExitValue(0);
126         oa.stdoutShouldMatch(terminated);
127 
128         switch(test) {
129             case "Normal":
130             case "MultiNormal":
131                 oa.stdoutShouldNotMatch(stillLocked);
132                 break;
133             case "MissingUnlock":
134                 oa.stdoutShouldMatch(stillLocked);
135                 break;
136             case "MultiMissingUnlock":
137                 parseOutputForPattern(oa.stdoutAsLines(), stillLocked, MULTI_THREAD_COUNT);
138                 break;
139             case "MissingUnlockWithThrow":
140                 oa.stdoutShouldMatch(stillLocked);
141                 oa.stderrShouldContain(throwMsg);

202         // unexpectedly, so we can force that condition too by shutting down our custom scheduler.
203         private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
204             Thread.Builder.OfVirtual builder = Thread.ofVirtual();
205             try {
206                 Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
207                 Constructor<?> ctor = clazz.getDeclaredConstructor(Executor.class);
208                 ctor.setAccessible(true);
209                 return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler);
210             } catch (InvocationTargetException e) {
211                 Throwable cause = e.getCause();
212                 if (cause instanceof RuntimeException re) {
213                     throw re;
214                 }
215                 throw new RuntimeException(e);
216             } catch (Exception e) {
217                 throw new RuntimeException(e);
218             }
219         }
220 
221         static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable {
222             final Object monitor = new Object();



223             final AtomicReference<Throwable> exception = new AtomicReference();
224             // Ensure all our VT's operate of the same carrier, sequentially.
225             ExecutorService scheduler = Executors.newSingleThreadExecutor();
226             ThreadFactory factory = virtualThreadBuilder(scheduler).factory();
227             for (int i = 0 ; i < nThreads; i++) {

228                 Thread th = factory.newThread(() -> {
229                         try {
230                             int res = monitorEnter(monitor);
231                             Asserts.assertTrue(res == 0, "monitorEnter should return 0.");
232                             Asserts.assertTrue(Thread.holdsLock(monitor), "monitor should be owned");
233                             Thread.yield();
234                             if (!skipUnlock) {
235                                 res = monitorExit(monitor);
236                                 Asserts.assertTrue(res == 0, "monitorExit should return 0.");
237                                 Asserts.assertFalse(Thread.holdsLock(monitor), "monitor should be unowned");
238                             }
239                         } catch (Throwable t) {
240                             exception.set(t);
241                         }
242                         if (throwOnExit) {
243                             throw new RuntimeException(throwMsg);
244                         }
245                     });
246                 th.start();
247                 th.join();

102  * @summary Don't do the unlock and exit by throwing, by multiple threads
103  * @library /test/lib
104  * @modules java.base/java.lang:+open
105  * @requires vm.continuations
106  * @run driver JNIMonitor MultiMissingUnlockWithThrow
107  */
108 
109 public class JNIMonitor {
110 
111     public static void main(String[] args) throws Exception {
112         String test = args[0];
113         String[] cmdArgs = new String[] {
114             "-Djava.library.path=" + Utils.TEST_NATIVE_PATH,
115             // Grant access to ThreadBuilders$VirtualThreadBuilder
116             "--add-opens=java.base/java.lang=ALL-UNNAMED",
117             // Enable the JNI warning
118             "-Xcheck:jni",
119             "-Xlog:jni=debug",
120             // Enable thread termination logging as a visual cross-check
121             "-Xlog:thread+os=info",
122             // We only count monitors in LM_LEGACY mode
123             "-XX:LockingMode=1",
124             "JNIMonitor$" + test,
125         };
126         OutputAnalyzer oa = ProcessTools.executeTestJava(cmdArgs);
127         oa.shouldHaveExitValue(0);
128         oa.stdoutShouldMatch(terminated);
129 
130         switch(test) {
131             case "Normal":
132             case "MultiNormal":
133                 oa.stdoutShouldNotMatch(stillLocked);
134                 break;
135             case "MissingUnlock":
136                 oa.stdoutShouldMatch(stillLocked);
137                 break;
138             case "MultiMissingUnlock":
139                 parseOutputForPattern(oa.stdoutAsLines(), stillLocked, MULTI_THREAD_COUNT);
140                 break;
141             case "MissingUnlockWithThrow":
142                 oa.stdoutShouldMatch(stillLocked);
143                 oa.stderrShouldContain(throwMsg);

204         // unexpectedly, so we can force that condition too by shutting down our custom scheduler.
205         private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) {
206             Thread.Builder.OfVirtual builder = Thread.ofVirtual();
207             try {
208                 Class<?> clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder");
209                 Constructor<?> ctor = clazz.getDeclaredConstructor(Executor.class);
210                 ctor.setAccessible(true);
211                 return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler);
212             } catch (InvocationTargetException e) {
213                 Throwable cause = e.getCause();
214                 if (cause instanceof RuntimeException re) {
215                     throw re;
216                 }
217                 throw new RuntimeException(e);
218             } catch (Exception e) {
219                 throw new RuntimeException(e);
220             }
221         }
222 
223         static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable {
224             final Object[] monitors = new Object[nThreads];
225             for (int i = 0; i < nThreads; i++) {
226                 monitors[i] = new Object();
227             }
228             final AtomicReference<Throwable> exception = new AtomicReference();
229             // Ensure all our VT's operate of the same carrier, sequentially.
230             ExecutorService scheduler = Executors.newSingleThreadExecutor();
231             ThreadFactory factory = virtualThreadBuilder(scheduler).factory();
232             for (int i = 0 ; i < nThreads; i++) {
233                 Object monitor = skipUnlock ? monitors[i] : monitors[0];
234                 Thread th = factory.newThread(() -> {
235                         try {
236                             int res = monitorEnter(monitor);
237                             Asserts.assertTrue(res == 0, "monitorEnter should return 0.");
238                             Asserts.assertTrue(Thread.holdsLock(monitor), "monitor should be owned");
239                             Thread.yield();
240                             if (!skipUnlock) {
241                                 res = monitorExit(monitor);
242                                 Asserts.assertTrue(res == 0, "monitorExit should return 0.");
243                                 Asserts.assertFalse(Thread.holdsLock(monitor), "monitor should be unowned");
244                             }
245                         } catch (Throwable t) {
246                             exception.set(t);
247                         }
248                         if (throwOnExit) {
249                             throw new RuntimeException(throwMsg);
250                         }
251                     });
252                 th.start();
253                 th.join();
< prev index next >