< 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  * @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     }

 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);

  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  * @modules java.base/java.lang:+open
 29  * @library /test/lib
 30  * @run junit/othervm/native --enable-native-access=ALL-UNNAMED GetThreadStateTest
 31  */
 32 
 33 /*
 34  * @test id=no-vmcontinuations
 35  * @requires vm.continuations
 36  * @modules java.base/java.lang:+open
 37  * @library /test/lib
 38  * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations --enable-native-access=ALL-UNNAMED GetThreadStateTest
 39  */
 40 
 41 import java.util.StringJoiner;
 42 import java.util.concurrent.atomic.AtomicBoolean;
 43 import java.util.concurrent.locks.LockSupport;
 44 
 45 import jdk.test.lib.thread.VThreadRunner;
 46 import jdk.test.lib.thread.VThreadPinner;
 47 import org.junit.jupiter.api.BeforeAll;
 48 import org.junit.jupiter.api.Test;
 49 import org.junit.jupiter.params.ParameterizedTest;
 50 import org.junit.jupiter.params.provider.ValueSource;
 51 import static org.junit.jupiter.api.Assertions.*;
 52 
 53 class GetThreadStateTest {
 54 
 55     @BeforeAll
 56     static void setup() {
 57         System.loadLibrary("GetThreadStateTest");
 58         init();
 59 
 60         // need >=2 carriers for testing pinning when main thread is a virtual thread
 61         if (Thread.currentThread().isVirtual()) {
 62             VThreadRunner.ensureParallelism(2);
 63         }
 64     }
 65 
 66     /**
 67      * Test state of new/unstarted thread.
 68      */
 69     @Test
 70     void testUnstarted() {
 71         var thread = Thread.ofVirtual().unstarted(() -> { });
 72         check(thread, /*new*/ 0);
 73     }
 74 
 75     /**
 76      * Test state of terminated thread.
 77      */
 78     @Test
 79     void testTerminated() throws Exception {
 80         var thread = Thread.ofVirtual().start(() -> { });
 81         thread.join();
 82         check(thread, JVMTI_THREAD_STATE_TERMINATED);
 83     }

 98             }
 99         });
100         try {
101             // wait for thread to start execution
102             awaitTrue(started);
103 
104             // thread should be runnable
105             int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE;
106             check(thread, expected);
107 
108             // re-test with interrupt status set
109             thread.interrupt();
110             check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
111         } finally {
112             done.set(true);
113             thread.join();
114         }
115     }
116 
117     /**
118      * Test state of thread waiting to enter a monitor when pinned and not pinned.
119      */
120     @ParameterizedTest
121     @ValueSource(booleans = { true, false })
122     void testMonitorEnter(boolean pinned) throws Exception {
123         var ready = new AtomicBoolean();
124         Object lock = new Object();
125         var thread = Thread.ofVirtual().unstarted(() -> {
126             if (pinned) {
127                 VThreadPinner.runPinned(() -> {
128                     ready.set(true);
129                     synchronized (lock) { }
130                 });
131             } else {
132                 ready.set(true);
133                 synchronized (lock) { }
134             }
135         });
136         try {
137             synchronized (lock) {
138                 // start thread and wait for it to start execution
139                 thread.start();
140                 awaitTrue(ready);
141 
142                 // thread should block on monitor enter
143                 int expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
144                 await(thread, expected);
145 
146                 // re-test with interrupt status set
147                 thread.interrupt();
148                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
149             }
150         } finally {
151             thread.join();
152         }
153     }
154 
155     /**
156      * Test state of thread waiting in Object.wait() when pinned and not pinned.
157      */
158     @ParameterizedTest
159     @ValueSource(booleans = { true, false })
160     void testObjectWait(boolean pinned) throws Exception {
161         var ready = new AtomicBoolean();
162         Object lock = new Object();
163         var thread = Thread.ofVirtual().start(() -> {
164             synchronized (lock) {

165                 try {
166                     if (pinned) {
167                         VThreadPinner.runPinned(() -> {
168                             ready.set(true);
169                             lock.wait();
170                         });
171                     } else {
172                         ready.set(true);
173                         lock.wait();
174                     }
175                 } catch (InterruptedException e) { }
176             }
177         });
178         try {
179             // wait for thread to start execution
180             awaitTrue(ready);
181 
182             // thread should wait
183             int expected = JVMTI_THREAD_STATE_ALIVE |
184                     JVMTI_THREAD_STATE_WAITING |
185                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
186                     JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
187             await(thread, expected);
188 
189             // notify so thread waits to re-enter monitor
190             synchronized (lock) {
191                 lock.notifyAll();
192                 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
193                 check(thread, expected);
194 
195                 // re-test with interrupt status set
196                 thread.interrupt();
197                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
198             }
199         } finally {
200             thread.interrupt();
201             thread.join();
202         }
203     }
204 
205     /**
206      * Test state of thread waiting in Object.wait(millis) when pinned and not pinned.
207      */
208     @ParameterizedTest
209     @ValueSource(booleans = { true, false })
210     void testObjectWaitMillis(boolean pinned) throws Exception {
211         var ready = new AtomicBoolean();
212         Object lock = new Object();
213         var thread = Thread.ofVirtual().start(() -> {
214             synchronized (lock) {
215                 synchronized (lock) {
216                     try {
217                         if (pinned) {
218                             VThreadPinner.runPinned(() -> {
219                                 ready.set(true);
220                                 lock.wait(Long.MAX_VALUE);
221                             });
222                         } else {
223                             ready.set(true);
224                             lock.wait(Long.MAX_VALUE);
225                         }
226                     } catch (InterruptedException e) { }
227                 }
228             }
229         });
230         try {
231             // wait for thread to start execution
232             awaitTrue(ready);
233 
234             // thread should wait
235             int expected = JVMTI_THREAD_STATE_ALIVE |
236                     JVMTI_THREAD_STATE_WAITING |
237                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
238                     JVMTI_THREAD_STATE_IN_OBJECT_WAIT;
239             await(thread, expected);
240 
241             // notify so thread waits to re-enter monitor
242             synchronized (lock) {
243                 lock.notifyAll();
244                 expected = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER;
245                 check(thread, expected);
246 
247                 // re-test with interrupt status set
248                 thread.interrupt();
249                 check(thread, expected | JVMTI_THREAD_STATE_INTERRUPTED);
250             }
251         } finally {
252             thread.interrupt();
253             thread.join();
254         }
255     }
256 
257     /**
258      * Test state of thread parked with LockSupport.park when pinned and not pinned.
259      */
260     @ParameterizedTest
261     @ValueSource(booleans = { true, false })
262     void testPark(boolean pinned) throws Exception {
263         var ready = new AtomicBoolean();
264         var done = new AtomicBoolean();
265         var thread = Thread.ofVirtual().start(() -> {
266             if (pinned) {
267                 VThreadPinner.runPinned(() -> {
268                     ready.set(true);
269                     while (!done.get()) {
270                         LockSupport.park();
271                     }
272                 });
273             } else {
274                 ready.set(true);





















































275                 while (!done.get()) {
276                     LockSupport.park();
277                 }
278             }
279         });
280         try {
281             // wait for thread to start execution
282             awaitTrue(ready);
283 
284             // thread should park
285             int expected = JVMTI_THREAD_STATE_ALIVE |
286                     JVMTI_THREAD_STATE_WAITING |
287                     JVMTI_THREAD_STATE_WAITING_INDEFINITELY |
288                     JVMTI_THREAD_STATE_PARKED;
289             await(thread, expected);
290         } finally {
291             done.set(true);
292             LockSupport.unpark(thread);
293             thread.join();
294         }
295     }
296 
297     /**
298      * Test state of thread parked with LockSupport.parkNanos when pinned and not pinned.
299      */
300     @ParameterizedTest
301     @ValueSource(booleans = { true, false })
302     void testParkNanos(boolean pinned) throws Exception {
303         var ready = new AtomicBoolean();
304         var done = new AtomicBoolean();
305         var thread = Thread.ofVirtual().start(() -> {
306             if (pinned) {
307                 VThreadPinner.runPinned(() -> {
308                     ready.set(true);
309                     while (!done.get()) {
310                         LockSupport.parkNanos(Long.MAX_VALUE);
311                     }
312                 });
313             } else {
314                 ready.set(true);
315                 while (!done.get()) {
316                     LockSupport.parkNanos(Long.MAX_VALUE);
317                 }
318             }
319         });
320         try {
321             // wait for thread to start execution
322             awaitTrue(ready);
323 
324             // thread should park
325             int expected = JVMTI_THREAD_STATE_ALIVE |
326                     JVMTI_THREAD_STATE_WAITING |
327                     JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT |
328                     JVMTI_THREAD_STATE_PARKED;
329             await(thread, expected);
330         } finally {
331             done.set(true);
332             LockSupport.unpark(thread);
333             thread.join();
334         }
335     }
336 
337     /**
338      * Waits for the boolean value to become true.
339      */
340     private static void awaitTrue(AtomicBoolean ref) throws Exception {
341         while (!ref.get()) {
342             Thread.sleep(20);
< prev index next >