< prev index next >

test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.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  * @summary Verifies JVMTI StopThread support for virtual threads.
 27  * @requires vm.continuations

 28  * @run main/othervm/native -agentlib:StopThreadTest StopThreadTest
 29  */
 30 
 31 /*
 32  * @test id=no-vmcontinuations
 33  * @summary Verifies JVMTI StopThread support for bound virtual threads.
 34  * @run main/othervm/native -agentlib:StopThreadTest -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations StopThreadTest

 35  */
 36 
 37 /*
 38  * @test id=platform
 39  * @summary Verifies JVMTI StopThread support for platform threads.

 40  * @run main/othervm/native -agentlib:StopThreadTest StopThreadTest platform
 41  */
 42 

 43 import java.lang.AssertionError;
 44 
 45 /*
 46  *     The test exercises the JVMTI function: StopThread(jthread).
 47  *     The test creates a new virtual or platform thread.
 48  *     Its method run() invokes the following methods:
 49  *      - method A() that is blocked on a monitor
 50  *      - method B() that is stopped at a breakpoint
 51  *      - method C() that forces agent to send AssertionError exception to its own thread
 52  *     All cases are using JVMTI StopThread to send an AssertionError object.
 53  */
 54 public class StopThreadTest {
 55     private static final String agentLib = "StopThreadTest";

 56     static final int JVMTI_ERROR_NONE = 0;

 57     static final int THREAD_NOT_SUSPENDED = 13;
 58     static final int PASSED = 0;
 59     static final int FAILED = 2;
 60 
 61     static void log(String str) { System.out.println(str); }
 62 
 63     static native void prepareAgent(Class taskClass, Object exceptionObject);
 64     static native void suspendThread(Thread thread);
 65     static native void resumeThread(Thread thread);
 66     static native void ensureAtBreakpoint();
 67     static native void notifyAtBreakpoint();
 68     static native int  stopThread(Thread thread);
 69 
 70     static int status = PASSED;
 71     static boolean is_virtual = true;
 72 
 73     static void setFailed(String msg) {
 74         log("\nFAILED: " + msg);
 75         status = FAILED;
 76     }

 87             throwFailed("StopThreadTest!");
 88         }
 89         log("\nStopThreadTest passed");
 90     }
 91 
 92     public static void run() {
 93         TestTask testTask = new TestTask();
 94         Thread testTaskThread = null;
 95         AssertionError excObject = new AssertionError();
 96         int retCode;
 97 
 98         prepareAgent(TestTask.class, excObject);
 99 
100         log("\nMain #A: method A() must be blocked on entering a synchronized statement");
101         synchronized (TestTask.lock) {
102             if (is_virtual) {
103                 testTaskThread = Thread.ofVirtual().name("TestTaskThread").start(testTask);
104             } else {
105                 testTaskThread = Thread.ofPlatform().name("TestTaskThread").start(testTask);
106             }
107             TestTask.ensureAtPointA();
108 
109             if (is_virtual) { // this check is for virtual target thread only
110                 log("\nMain #A.1: unsuspended");
111                 retCode = stopThread(testTaskThread);
112                 if (retCode != THREAD_NOT_SUSPENDED) {
113                     throwFailed("Main #A.1: expected THREAD_NOT_SUSPENDED instead of: " + retCode);
114                 } else {
115                     log("Main #A.1: got expected THREAD_NOT_SUSPENDED");
116                 }
117             }
118 
119             log("\nMain #A.2: suspended");
120             suspendThread(testTaskThread);
121             retCode = stopThread(testTaskThread);
122             if (retCode != JVMTI_ERROR_NONE) {
123                 throwFailed("Main #A.2: expected JVMTI_ERROR_NONE instead of: " + retCode);



124             } else {
125                 log("Main #A.2: got expected JVMTI_ERROR_NONE");
126             }
127             resumeThread(testTaskThread);
128         }
129         log("\nMain #B: method B() must be blocked in a breakpoint event handler");
130         {
131             ensureAtBreakpoint();
132 
133             if (is_virtual) { // this check is for virtual target thread only
134                 log("\nMain #B.1: unsuspended");
135                 retCode = stopThread(testTaskThread);
136                 if (retCode != THREAD_NOT_SUSPENDED) {
137                     throwFailed("Main #B.1: expected THREAD_NOT_SUSPENDED instead of: " + retCode);
138                 }
139             }
140 
141             log("\nMain #B.2: suspended");
142             suspendThread(testTaskThread);
143             retCode = stopThread(testTaskThread);
144             if (retCode != JVMTI_ERROR_NONE) {
145                 throwFailed("Main #B.2: expected JVMTI_ERROR_NONE");

162             throwFailed("Unexpected " + ex);
163         }
164     }
165 
166 
167     static class TestTask implements Runnable {
168         static Object lock = new Object();
169         static void log(String str) { System.out.println(str); }
170 
171         static volatile boolean atPointA = false;
172         static volatile boolean finished = false;
173 
174         static void sleep(long millis) {
175             try {
176                 Thread.sleep(millis);
177             } catch (InterruptedException e) {
178                 throw new RuntimeException("Interruption in TestTask.sleep: \n\t" + e);
179             }
180         }
181 
182         static void ensureAtPointA() {
183             while (!atPointA) {

184                 sleep(1);
185             }
186         }
187 
188         // Ensure thread is finished.
189         static void ensureFinished() {
190             while (!finished) {
191                 sleep(1);
192             }
193         }
194 
195         public void run() {
196             log("TestTask.run: started");
197 
198             boolean seenExceptionFromA = false;
199             try {
200                 A();
201             } catch (AssertionError ex) {
202                 log("TestTask.run: caught expected AssertionError from method A()");
203                 seenExceptionFromA = true;
204             }
205             Thread.interrupted();
206             if (!seenExceptionFromA) {



207                 StopThreadTest.setFailed("TestTask.run: expected AssertionError from method A()");
208             }
209             sleep(1); // to cause yield
210 
211             boolean seenExceptionFromB = false;
212             try {
213               B();
214             } catch (AssertionError ex) {
215                 log("TestTask.run: caught expected AssertionError from method B()");
216                 seenExceptionFromB = true;
217             }
218             Thread.interrupted();
219             if (!seenExceptionFromB) {
220                 StopThreadTest.setFailed("TestTask.run: expected AssertionError from method B()");
221             }
222             sleep(1); // to cause yield
223 
224             boolean seenExceptionFromC = false;
225             try {
226                 C();
227             } catch (AssertionError ex) {
228                 log("TestTask.run: caught expected AssertionError from method C()");
229                 seenExceptionFromC = true;
230             }
231             Thread.interrupted();
232             if (!seenExceptionFromC) {
233                 StopThreadTest.setFailed("TestTask.run: expected AssertionError from method C()");
234             }
235             finished = true;
236         }
237 
238         // Method is blocked on entering a synchronized statement.
239         // StopThread is used to send an AssertionError object two times:
240         //  - when not suspended: THREAD_NOT_SUSPENDED is expected
241         //  - when suspended: JVMTI_ERROR_NONE is expected
242         static void A() {
243             log("TestTask.A: started");
244             atPointA = true;
245             synchronized (lock) {
246             }
247             log("TestTask.A: finished");
248         }
249 
250         // A breakpoint is set at start of this method.
251         // StopThread is used to send an AssertionError object two times:
252         //  - when not suspended: THREAD_NOT_SUSPENDED is expected
253         //  - when suspended: expected to succeed
254         static void B() {
255             log("TestTask.B: started");
256         }
257 
258         // This method uses StopThread to send an AssertionError object to
259         // its own thread. It is expected to succeed.
260         static void C() {
261             log("TestTask.C: started");
262             StopThreadTest.stopThread(Thread.currentThread());
263             log("TestTask.C: finished");
264         }

  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  * @summary Verifies JVMTI StopThread support for virtual threads.
 27  * @requires vm.continuations
 28  * @library /test/lib
 29  * @run main/othervm/native -agentlib:StopThreadTest StopThreadTest
 30  */
 31 
 32 /*
 33  * @test id=no-vmcontinuations
 34  * @summary Verifies JVMTI StopThread support for bound virtual threads.
 35  * @library /test/lib
 36  * @run main/othervm/native -agentlib:StopThreadTest -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations -DboundVThread=true StopThreadTest
 37  */
 38 
 39 /*
 40  * @test id=platform
 41  * @summary Verifies JVMTI StopThread support for platform threads.
 42  * @library /test/lib
 43  * @run main/othervm/native -agentlib:StopThreadTest StopThreadTest platform
 44  */
 45 
 46 import jdk.test.lib.Platform;
 47 import java.lang.AssertionError;
 48 
 49 /*
 50  *     The test exercises the JVMTI function: StopThread(jthread).
 51  *     The test creates a new virtual or platform thread.
 52  *     Its method run() invokes the following methods:
 53  *      - method A() that is blocked on a monitor
 54  *      - method B() that is stopped at a breakpoint
 55  *      - method C() that forces agent to send AssertionError exception to its own thread
 56  *     All cases are using JVMTI StopThread to send an AssertionError object.
 57  */
 58 public class StopThreadTest {
 59     private static final String agentLib = "StopThreadTest";
 60     static final boolean isBoundVThread = Boolean.getBoolean("boundVThread");
 61     static final int JVMTI_ERROR_NONE = 0;
 62     static final int JVMTI_ERROR_OPAQUE_FRAME = 32;
 63     static final int THREAD_NOT_SUSPENDED = 13;
 64     static final int PASSED = 0;
 65     static final int FAILED = 2;
 66 
 67     static void log(String str) { System.out.println(str); }
 68 
 69     static native void prepareAgent(Class taskClass, Object exceptionObject);
 70     static native void suspendThread(Thread thread);
 71     static native void resumeThread(Thread thread);
 72     static native void ensureAtBreakpoint();
 73     static native void notifyAtBreakpoint();
 74     static native int  stopThread(Thread thread);
 75 
 76     static int status = PASSED;
 77     static boolean is_virtual = true;
 78 
 79     static void setFailed(String msg) {
 80         log("\nFAILED: " + msg);
 81         status = FAILED;
 82     }

 93             throwFailed("StopThreadTest!");
 94         }
 95         log("\nStopThreadTest passed");
 96     }
 97 
 98     public static void run() {
 99         TestTask testTask = new TestTask();
100         Thread testTaskThread = null;
101         AssertionError excObject = new AssertionError();
102         int retCode;
103 
104         prepareAgent(TestTask.class, excObject);
105 
106         log("\nMain #A: method A() must be blocked on entering a synchronized statement");
107         synchronized (TestTask.lock) {
108             if (is_virtual) {
109                 testTaskThread = Thread.ofVirtual().name("TestTaskThread").start(testTask);
110             } else {
111                 testTaskThread = Thread.ofPlatform().name("TestTaskThread").start(testTask);
112             }
113             TestTask.ensureAtPointA(testTaskThread);
114 
115             if (is_virtual) { // this check is for virtual target thread only
116                 log("\nMain #A.1: unsuspended");
117                 retCode = stopThread(testTaskThread);
118                 if (retCode != THREAD_NOT_SUSPENDED) {
119                     throwFailed("Main #A.1: expected THREAD_NOT_SUSPENDED instead of: " + retCode);
120                 } else {
121                     log("Main #A.1: got expected THREAD_NOT_SUSPENDED");
122                 }
123             }
124 
125             log("\nMain #A.2: suspended");
126             suspendThread(testTaskThread);
127             retCode = stopThread(testTaskThread);
128             int expectedRetCode = (is_virtual && !isBoundVThread && (Platform.isX64() || Platform.isAArch64())) ? JVMTI_ERROR_OPAQUE_FRAME : JVMTI_ERROR_NONE;
129             String expectedRetCodeName = (is_virtual && !isBoundVThread && (Platform.isX64() || Platform.isAArch64())) ?
130                 "JVMTI_ERROR_OPAQUE_FRAME" : "JVMTI_ERROR_NONE";
131             if (retCode != expectedRetCode) {
132                 throwFailed("Main #A.2: expected " + expectedRetCodeName + " instead of: " + retCode);
133             } else {
134                 log("Main #A.2: got expected " + expectedRetCodeName);
135             }
136             resumeThread(testTaskThread);
137         }
138         log("\nMain #B: method B() must be blocked in a breakpoint event handler");
139         {
140             ensureAtBreakpoint();
141 
142             if (is_virtual) { // this check is for virtual target thread only
143                 log("\nMain #B.1: unsuspended");
144                 retCode = stopThread(testTaskThread);
145                 if (retCode != THREAD_NOT_SUSPENDED) {
146                     throwFailed("Main #B.1: expected THREAD_NOT_SUSPENDED instead of: " + retCode);
147                 }
148             }
149 
150             log("\nMain #B.2: suspended");
151             suspendThread(testTaskThread);
152             retCode = stopThread(testTaskThread);
153             if (retCode != JVMTI_ERROR_NONE) {
154                 throwFailed("Main #B.2: expected JVMTI_ERROR_NONE");

171             throwFailed("Unexpected " + ex);
172         }
173     }
174 
175 
176     static class TestTask implements Runnable {
177         static Object lock = new Object();
178         static void log(String str) { System.out.println(str); }
179 
180         static volatile boolean atPointA = false;
181         static volatile boolean finished = false;
182 
183         static void sleep(long millis) {
184             try {
185                 Thread.sleep(millis);
186             } catch (InterruptedException e) {
187                 throw new RuntimeException("Interruption in TestTask.sleep: \n\t" + e);
188             }
189         }
190 
191         static void ensureAtPointA(Thread vt) {
192             // wait while the thread state is not the expected one
193             while (vt.getState() != Thread.State.BLOCKED) {
194                 sleep(1);
195             }
196         }
197 
198         // Ensure thread is finished.
199         static void ensureFinished() {
200             while (!finished) {
201                 sleep(1);
202             }
203         }
204 
205         public void run() {
206             log("TestTask.run: started");
207 
208             boolean seenExceptionFromA = false;
209             try {
210                 A();
211             } catch (AssertionError ex) {
212                 log("TestTask.run: caught expected AssertionError from method A()");
213                 seenExceptionFromA = true;
214             }
215             Thread.interrupted();
216             if (!seenExceptionFromA
217                 && !(is_virtual
218                      && !isBoundVThread
219                      && (Platform.isX64() || (Platform.isAArch64())) )) {
220                 StopThreadTest.setFailed("TestTask.run: expected AssertionError from method A()");
221             }
222             sleep(1); // to cause yield
223 
224             boolean seenExceptionFromB = false;
225             try {
226               B();
227             } catch (AssertionError ex) {
228                 log("TestTask.run: caught expected AssertionError from method B()");
229                 seenExceptionFromB = true;
230             }
231             Thread.interrupted();
232             if (!seenExceptionFromB) {
233                 StopThreadTest.setFailed("TestTask.run: expected AssertionError from method B()");
234             }
235             sleep(1); // to cause yield
236 
237             boolean seenExceptionFromC = false;
238             try {
239                 C();
240             } catch (AssertionError ex) {
241                 log("TestTask.run: caught expected AssertionError from method C()");
242                 seenExceptionFromC = true;
243             }
244             Thread.interrupted();
245             if (!seenExceptionFromC) {
246                 StopThreadTest.setFailed("TestTask.run: expected AssertionError from method C()");
247             }
248             finished = true;
249         }
250 
251         // Method is blocked on entering a synchronized statement.
252         // StopThread is used to send an AssertionError object two times:
253         //  - when not suspended: THREAD_NOT_SUSPENDED is expected
254         //  - when suspended: JVMTI_ERROR_NONE is expected
255         static void A() {
256             log("TestTask.A: started");

257             synchronized (lock) {
258             }
259             log("TestTask.A: finished");
260         }
261 
262         // A breakpoint is set at start of this method.
263         // StopThread is used to send an AssertionError object two times:
264         //  - when not suspended: THREAD_NOT_SUSPENDED is expected
265         //  - when suspended: expected to succeed
266         static void B() {
267             log("TestTask.B: started");
268         }
269 
270         // This method uses StopThread to send an AssertionError object to
271         // its own thread. It is expected to succeed.
272         static void C() {
273             log("TestTask.C: started");
274             StopThreadTest.stopThread(Thread.currentThread());
275             log("TestTask.C: finished");
276         }
< prev index next >