< prev index next >

test/hotspot/jtreg/serviceability/jvmti/vthread/GetThreadState/GetThreadStateTest.java

Print this page

  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test id=default
 26  * @bug 8312498
 27  * @summary Basic test for JVMTI GetThreadState with virtual threads

 28  * @run junit/othervm/native GetThreadStateTest
 29  */
 30 
 31 /*
 32  * @test id=no-vmcontinuations
 33  * @requires vm.continuations

 34  * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations GetThreadStateTest
 35  */
 36 
 37 import java.util.StringJoiner;
 38 import java.util.concurrent.CountDownLatch;
 39 import java.util.concurrent.atomic.AtomicBoolean;
 40 import java.util.concurrent.locks.LockSupport;
 41 

 42 import org.junit.jupiter.api.BeforeAll;
 43 import org.junit.jupiter.api.Test;
 44 import static org.junit.jupiter.api.Assertions.*;
 45 
 46 class GetThreadStateTest {
 47 
 48     @BeforeAll
 49     static void setup() {
 50         System.loadLibrary("GetThreadStateTest");
 51         init();
 52     }
 53 
 54     /**
 55      * Test state of new/unstarted thread.
 56      */
 57     @Test
 58     void testUnstarted() {
 59         var thread = Thread.ofVirtual().unstarted(() -> { });
 60         check(thread, /*new*/ 0);
 61     }
 62 
 63     /**
 64      * Test state of terminated thread.
 65      */
 66     @Test
 67     void testTerminated() throws Exception {
 68         var thread = Thread.ofVirtual().start(() -> { });
 69         thread.join();
 70         check(thread, JVMTI_THREAD_STATE_TERMINATED);
 71     }
 72 
 73     /**
 74      * Test state of runnable thread.
 75      */
 76     @Test
 77     void testRunnable() throws Exception {
 78         var latch = new CountDownLatch(1);
 79         var done = new AtomicBoolean();
 80         var thread = Thread.ofVirtual().start(() -> {
 81             latch.countDown();
 82 
 83             // spin until done
 84             while (!done.get()) {
 85                 Thread.onSpinWait();
 86             }
 87         });
 88         try {
 89             // wait for thread to start execution
 90             latch.await();
 91 
 92             // thread should be runnable
 93             int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE;
 94             check(thread, expected);
 95 
 96             // re-test with interrupt status set
 97             thread.interrupt();
 98             check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
 99         } finally {
100             done.set(true);
101             thread.join();
102         }
103     }
104 
105     /**
106      * Test state of thread waiting to enter a monitor.
107      */
108     @Test
109     void testMonitorEnter() throws Exception {
110         var latch = new CountDownLatch(1);
111         Object lock = new Object();
112         var thread = Thread.ofVirtual().unstarted(() -> {
113             latch.countDown();
114             synchronized (lock) { }
115         });
116         try {
117             synchronized (lock) {
118                 // start thread and wait for it to start execution
119                 thread.start();
120                 latch.await();
121 
122                 // thread should block on monitor enter
123                 int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
124                 await(thread, expected);
125 
126                 // re-test with interrupt status set
127                 thread.interrupt();
128                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
129             }
130         } finally {
131             thread.join();
132         }
133     }
134 
135     /**
136      * Test state of thread waiting in Object.wait().
137      */
138     @Test
139     void testObjectWait() throws Exception {
140         var latch = new CountDownLatch(1);
141         Object lock = new Object();
142         var thread = Thread.ofVirtual().start(() -> {
143             synchronized (lock) {
144                 latch.countDown();
145                 try {
146                     lock.wait();
147                 } catch (InterruptedException e) { }
148             }
149         });
150         try {
151             // wait for thread to own monitor
152             latch.await();
153 
154             // thread should wait
155             int expected = JVMTI_THREAD_STATE_ALIVE |
156                     JVMTI_THREAD_STATE_WAITING |
157                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
158                     JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
159             await(thread, expected);
160 
161             // notify so thread waits to re-enter monitor
162             synchronized (lock) {
163                 lock.notifyAll();
164                 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
165                 check(thread, expected);
166 
167                 // re-test with interrupt status set
168                 thread.interrupt();
169                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
170             }
171         } finally {
172             thread.interrupt();
173             thread.join();
174         }
175     }
176 
177     /**
178      * Test state of thread waiting in Object.wait(millis).
179      */
180     @Test
181     void testObjectWaitMillis() throws Exception {
182         var latch = new CountDownLatch(1);
183         Object lock = new Object();
184         var thread = Thread.ofVirtual().start(() -> {
185             synchronized (lock) {
186                 latch.countDown();
187                 try {
188                     lock.wait(Long.MAX_VALUE);
189                 } catch (InterruptedException e) { }
190             }
191         });
192         try {
193             // wait for thread to own monitor
194             latch.await();
195 
196             // thread should wait
197             int expected = JVMTI_THREAD_STATE_ALIVE |
198                     JVMTI_THREAD_STATE_WAITING |
199                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
200                     JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
201             await(thread, expected);
202 
203             // notify so thread waits to re-enter monitor
204             synchronized (lock) {
205                 lock.notifyAll();
206                 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
207                 check(thread, expected);
208 
209                 // re-test with interrupt status set
210                 thread.interrupt();
211                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
212             }
213         } finally {
214             thread.interrupt();
215             thread.join();
216         }
217     }
218 
219     /**
220      * Test state of thread parked with LockSupport.park.
221      */
222     @Test
223     void testPark() throws Exception {
224         var latch = new CountDownLatch(1);
225         var done = new AtomicBoolean();
226         var thread = Thread.ofVirtual().start(() -> {
227             latch.countDown();
228             while (!done.get()) {
229                 LockSupport.park();
230             }
231         });
232         try {
233             // wait for thread to start execution
234             latch.await();
235 
236             // thread should park
237             int expected = JVMTI_THREAD_STATE_ALIVE |
238                     JVMTI_THREAD_STATE_WAITING |
239                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
240                     JVMTI_THREAD_STATE_PARKED;
241             await(thread, expected);
242         } finally {
243             done.set(true);
244             LockSupport.unpark(thread);
245             thread.join();
246         }
247     }
248 
249     /**
250      * Test state of thread parked with LockSupport.parkNanos.
251      */
252     @Test
253     void testParkNanos() throws Exception {
254         var latch = new CountDownLatch(1);
255         var done = new AtomicBoolean();
256         var thread = Thread.ofVirtual().start(() -> {
257             latch.countDown();
258             while (!done.get()) {
259                 LockSupport.parkNanos(Long.MAX_VALUE);
260             }
261         });
262         try {
263             // wait for thread to start execution
264             latch.await();
265 
266             // thread should park
267             int expected = JVMTI_THREAD_STATE_ALIVE |
268                     JVMTI_THREAD_STATE_WAITING |
269                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
270                     JVMTI_THREAD_STATE_PARKED;
271             await(thread, expected);
272         } finally {
273             done.set(true);
274             LockSupport.unpark(thread);
275             thread.join();
276         }
277     }
278 
279     /**
280      * Test state of thread parked with LockSupport.park while holding a monitor.
281      */
282     @Test
283     void testParkWhenPinned() throws Exception {
284         var latch = new CountDownLatch(1);
285         Object lock = new Object();
286         var done = new AtomicBoolean();
287         var thread = Thread.ofVirtual().start(() -> {
288             synchronized (lock) {
289                 latch.countDown();
290                 while (!done.get()) {
291                     LockSupport.park();
292                 }
293             }
294         });
295         try {
296             // wait for thread to own monitor
297             latch.await();
298 
299             // thread should park
300             int expected = JVMTI_THREAD_STATE_ALIVE |
301                     JVMTI_THREAD_STATE_WAITING |
302                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
303                     JVMTI_THREAD_STATE_PARKED;
304             await(thread, expected);
305         } finally {
306             done.set(true);
307             LockSupport.unpark(thread);
308             thread.join();
309         }
310     }
311 
312     /**
313      * Test state of thread parked with LockSupport.parkNanos while holding a monitor.
314      */
315     @Test
316     void testParkNanosWhenPinned() throws Exception {
317         var latch = new CountDownLatch(1);
318         Object lock = new Object();
319         var done = new AtomicBoolean();
320         var thread = Thread.ofVirtual().start(() -> {
321             synchronized (lock) {
322                 latch.countDown();
323                 while (!done.get()) {
324                     LockSupport.parkNanos(Long.MAX_VALUE);
325                 }
326             }
327         });
328         try {
329             // wait for thread to own monitor
330             latch.await();
331 
332             // thread should park
333             int expected = JVMTI_THREAD_STATE_ALIVE |
334                     JVMTI_THREAD_STATE_WAITING |
335                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
336                     JVMTI_THREAD_STATE_PARKED;
337             await(thread, expected);
338         } finally {
339             done.set(true);
340             LockSupport.unpark(thread);
341             thread.join();
342         }
343     }
344 









345     /**
346      * Asserts that the given thread has the expected JVMTI state.
347      */
348     private static void check(Thread thread, int expected) {
349         System.err.format("  expect state=0x%x (%s) ...%n", expected, jvmtiStateToString(expected));
350         int state = jvmtiState(thread);
351         System.err.format("  thread state=0x%x (%s)%n", state, jvmtiStateToString(state));
352         assertEquals(expected, state);
353     }
354 
355     /**
356      * Waits indefinitely for the given thread to get to the target JVMTI state.
357      */
358     private static void await(Thread thread, int targetState) throws Exception {
359         System.err.format("  await state=0x%x (%s) ...%n", targetState, jvmtiStateToString(targetState));
360         int state = jvmtiState(thread);
361         System.err.format("  thread state=0x%x (%s)%n", state, jvmtiStateToString(state));
362         while (state != targetState) {
363             assertTrue(thread.isAlive(), "Thread has terminated");
364             Thread.sleep(20);

  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test id=default
 26  * @bug 8312498
 27  * @summary Basic test for JVMTI GetThreadState with virtual threads
 28  * @library /test/lib
 29  * @run junit/othervm/native GetThreadStateTest
 30  */
 31 
 32 /*
 33  * @test id=no-vmcontinuations
 34  * @requires vm.continuations
 35  * @library /test/lib
 36  * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations GetThreadStateTest
 37  */
 38 
 39 import java.util.StringJoiner;

 40 import java.util.concurrent.atomic.AtomicBoolean;
 41 import java.util.concurrent.locks.LockSupport;
 42 
 43 import jdk.test.lib.thread.VThreadPinner;
 44 import org.junit.jupiter.api.BeforeAll;
 45 import org.junit.jupiter.api.Test;
 46 import static org.junit.jupiter.api.Assertions.*;
 47 
 48 class GetThreadStateTest {
 49 
 50     @BeforeAll
 51     static void setup() {
 52         System.loadLibrary("GetThreadStateTest");
 53         init();
 54     }
 55 
 56     /**
 57      * Test state of new/unstarted thread.
 58      */
 59     @Test
 60     void testUnstarted() {
 61         var thread = Thread.ofVirtual().unstarted(() -> { });
 62         check(thread, /*new*/ 0);
 63     }
 64 
 65     /**
 66      * Test state of terminated thread.
 67      */
 68     @Test
 69     void testTerminated() throws Exception {
 70         var thread = Thread.ofVirtual().start(() -> { });
 71         thread.join();
 72         check(thread, JVMTI_THREAD_STATE_TERMINATED);
 73     }
 74 
 75     /**
 76      * Test state of runnable thread.
 77      */
 78     @Test
 79     void testRunnable() throws Exception {
 80         var started = new AtomicBoolean();
 81         var done = new AtomicBoolean();
 82         var thread = Thread.ofVirtual().start(() -> {
 83             started.set(true);
 84 
 85             // spin until done
 86             while (!done.get()) {
 87                 Thread.onSpinWait();
 88             }
 89         });
 90         try {
 91             // wait for thread to start execution
 92             awaitTrue(started);
 93 
 94             // thread should be runnable
 95             int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE;
 96             check(thread, expected);
 97 
 98             // re-test with interrupt status set
 99             thread.interrupt();
100             check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
101         } finally {
102             done.set(true);
103             thread.join();
104         }
105     }
106 
107     /**
108      * Test state of thread waiting to enter a monitor.
109      */
110     @Test
111     void testMonitorEnter() throws Exception {
112         var started = new AtomicBoolean();
113         Object lock = new Object();
114         var thread = Thread.ofVirtual().unstarted(() -> {
115             started.set(true);
116             synchronized (lock) { }
117         });
118         try {
119             synchronized (lock) {
120                 // start thread and wait for it to start execution
121                 thread.start();
122                 awaitTrue(started);
123 
124                 // thread should block on monitor enter
125                 int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
126                 await(thread, expected);
127 
128                 // re-test with interrupt status set
129                 thread.interrupt();
130                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
131             }
132         } finally {
133             thread.join();
134         }
135     }
136 
137     /**
138      * Test state of thread waiting in Object.wait().
139      */
140     @Test
141     void testObjectWait() throws Exception {
142         var started = new AtomicBoolean();
143         Object lock = new Object();
144         var thread = Thread.ofVirtual().start(() -> {
145             synchronized (lock) {
146                 started.set(true);
147                 try {
148                     lock.wait();
149                 } catch (InterruptedException e) { }
150             }
151         });
152         try {
153             // wait for thread to start execution
154             awaitTrue(started);
155 
156             // thread should wait
157             int expected = JVMTI_THREAD_STATE_ALIVE |
158                     JVMTI_THREAD_STATE_WAITING |
159                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
160                     JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
161             await(thread, expected);
162 
163             // notify so thread waits to re-enter monitor
164             synchronized (lock) {
165                 lock.notifyAll();
166                 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
167                 check(thread, expected);
168 
169                 // re-test with interrupt status set
170                 thread.interrupt();
171                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
172             }
173         } finally {
174             thread.interrupt();
175             thread.join();
176         }
177     }
178 
179     /**
180      * Test state of thread waiting in Object.wait(millis).
181      */
182     @Test
183     void testObjectWaitMillis() throws Exception {
184         var started = new AtomicBoolean();
185         Object lock = new Object();
186         var thread = Thread.ofVirtual().start(() -> {
187             synchronized (lock) {
188                 started.set(true);
189                 try {
190                     lock.wait(Long.MAX_VALUE);
191                 } catch (InterruptedException e) { }
192             }
193         });
194         try {
195             // wait for thread to start execution
196             awaitTrue(started);
197 
198             // thread should wait
199             int expected = JVMTI_THREAD_STATE_ALIVE |
200                     JVMTI_THREAD_STATE_WAITING |
201                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
202                     JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
203             await(thread, expected);
204 
205             // notify so thread waits to re-enter monitor
206             synchronized (lock) {
207                 lock.notifyAll();
208                 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
209                 check(thread, expected);
210 
211                 // re-test with interrupt status set
212                 thread.interrupt();
213                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
214             }
215         } finally {
216             thread.interrupt();
217             thread.join();
218         }
219     }
220 
221     /**
222      * Test state of thread parked with LockSupport.park.
223      */
224     @Test
225     void testPark() throws Exception {
226         var started = new AtomicBoolean();
227         var done = new AtomicBoolean();
228         var thread = Thread.ofVirtual().start(() -> {
229             started.set(true);
230             while (!done.get()) {
231                 LockSupport.park();
232             }
233         });
234         try {
235             // wait for thread to start execution
236             awaitTrue(started);
237 
238             // thread should park
239             int expected = JVMTI_THREAD_STATE_ALIVE |
240                     JVMTI_THREAD_STATE_WAITING |
241                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
242                     JVMTI_THREAD_STATE_PARKED;
243             await(thread, expected);
244         } finally {
245             done.set(true);
246             LockSupport.unpark(thread);
247             thread.join();
248         }
249     }
250 
251     /**
252      * Test state of thread parked with LockSupport.parkNanos.
253      */
254     @Test
255     void testParkNanos() throws Exception {
256         var started = new AtomicBoolean();
257         var done = new AtomicBoolean();
258         var thread = Thread.ofVirtual().start(() -> {
259             started.set(true);
260             while (!done.get()) {
261                 LockSupport.parkNanos(Long.MAX_VALUE);
262             }
263         });
264         try {
265             // wait for thread to start execution
266             awaitTrue(started);
267 
268             // thread should park
269             int expected = JVMTI_THREAD_STATE_ALIVE |
270                     JVMTI_THREAD_STATE_WAITING |
271                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
272                     JVMTI_THREAD_STATE_PARKED;
273             await(thread, expected);
274         } finally {
275             done.set(true);
276             LockSupport.unpark(thread);
277             thread.join();
278         }
279     }
280 
281     /**
282      * Test state of thread parked with LockSupport.park while holding a monitor.
283      */
284     @Test
285     void testParkWhenPinned() throws Exception {
286         var started = new AtomicBoolean();

287         var done = new AtomicBoolean();
288         var thread = Thread.ofVirtual().start(() -> {
289             VThreadPinner.runPinned(() -> {
290                 started.set(true);
291                 while (!done.get()) {
292                     LockSupport.park();
293                 }
294             });
295         });
296         try {
297             // wait for thread to start execution
298             awaitTrue(started);
299 
300             // thread should park
301             int expected = JVMTI_THREAD_STATE_ALIVE |
302                     JVMTI_THREAD_STATE_WAITING |
303                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
304                     JVMTI_THREAD_STATE_PARKED;
305             await(thread, expected);
306         } finally {
307             done.set(true);
308             LockSupport.unpark(thread);
309             thread.join();
310         }
311     }
312 
313     /**
314      * Test state of thread parked with LockSupport.parkNanos while holding a monitor.
315      */
316     @Test
317     void testParkNanosWhenPinned() throws Exception {
318         var started = new AtomicBoolean();

319         var done = new AtomicBoolean();
320         var thread = Thread.ofVirtual().start(() -> {
321             VThreadPinner.runPinned(() -> {
322                 started.set(true);
323                 while (!done.get()) {
324                     LockSupport.parkNanos(Long.MAX_VALUE);
325                 }
326             });
327         });
328         try {
329             // wait for thread to start execution
330             awaitTrue(started);
331 
332             // thread should park
333             int expected = JVMTI_THREAD_STATE_ALIVE |
334                     JVMTI_THREAD_STATE_WAITING |
335                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
336                     JVMTI_THREAD_STATE_PARKED;
337             await(thread, expected);
338         } finally {
339             done.set(true);
340             LockSupport.unpark(thread);
341             thread.join();
342         }
343     }
344 
345     /**
346      * Waits for the boolean value to become true.
347      */
348     private static void awaitTrue(AtomicBoolean ref) throws Exception {
349         while (!ref.get()) {
350             Thread.sleep(20);
351         }
352     }
353 
354     /**
355      * Asserts that the given thread has the expected JVMTI state.
356      */
357     private static void check(Thread thread, int expected) {
358         System.err.format("  expect state=0x%x (%s) ...%n", expected, jvmtiStateToString(expected));
359         int state = jvmtiState(thread);
360         System.err.format("  thread state=0x%x (%s)%n", state, jvmtiStateToString(state));
361         assertEquals(expected, state);
362     }
363 
364     /**
365      * Waits indefinitely for the given thread to get to the target JVMTI state.
366      */
367     private static void await(Thread thread, int targetState) throws Exception {
368         System.err.format("  await state=0x%x (%s) ...%n", targetState, jvmtiStateToString(targetState));
369         int state = jvmtiState(thread);
370         System.err.format("  thread state=0x%x (%s)%n", state, jvmtiStateToString(state));
371         while (state != targetState) {
372             assertTrue(thread.isAlive(), "Thread has terminated");
373             Thread.sleep(20);
< prev index next >