Skip to content

Commit e18cd90

Browse files
committed
8283467: runtime/Thread/StopAtExit.java needs updating
Backport-of: a7e988343c7fda5b0f37e477f29cb172b908394d
1 parent b666008 commit e18cd90

File tree

2 files changed

+106
-12
lines changed

2 files changed

+106
-12
lines changed

test/hotspot/jtreg/runtime/Thread/StopAtExit.java

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@
2323

2424
/**
2525
* @test
26-
* @bug 8167108 8266130 8282704
27-
* @summary Stress test java.lang.Thread.stop() at thread exit.
26+
* @bug 8167108 8266130 8282704 8283467
27+
* @summary Stress test JVM/TI StopThread() at thread exit.
28+
* @requires vm.jvmti
2829
* @modules java.base/java.lang:open
29-
* @run main/othervm StopAtExit
30+
* @run main/othervm/native -agentlib:StopAtExit StopAtExit
3031
*/
3132

3233
import java.lang.reflect.Method;
@@ -36,10 +37,13 @@
3637
public class StopAtExit extends Thread {
3738
private final static int DEF_TIME_MAX = 30; // default max # secs to test
3839
private final static String PROG_NAME = "StopAtExit";
40+
private final static int JVMTI_ERROR_THREAD_NOT_ALIVE = 15;
3941

4042
public CountDownLatch exitSyncObj = new CountDownLatch(1);
4143
public CountDownLatch startSyncObj = new CountDownLatch(1);
4244

45+
native static int stopThread(StopAtExit thr, Throwable exception);
46+
4347
public StopAtExit(ThreadGroup group, Runnable target) {
4448
super(group, target);
4549
}
@@ -56,9 +60,9 @@ public void run() {
5660
throw new RuntimeException("Unexpected: " + e);
5761
}
5862
} catch (ThreadDeath td) {
59-
// ignore because we're testing Thread.stop() which throws it
63+
// ignore because we're testing JVM/TI StopThread() which throws it
6064
} catch (NoClassDefFoundError ncdfe) {
61-
// ignore because we're testing Thread.stop() which can cause it
65+
// ignore because we're testing JVM/TI StopThread() which can cause it
6266
}
6367
}
6468

@@ -89,27 +93,40 @@ public static void main(String[] args) {
8993
// the thread is terminated.
9094
ThreadGroup myTG = new ThreadGroup("myTG-" + count);
9195
myTG.setDaemon(true);
96+
Throwable myException = new ThreadDeath();
97+
int retCode;
9298
StopAtExit thread = new StopAtExit(myTG, null);
9399
thread.start();
94100
try {
95101
// Wait for the worker thread to get going.
96102
thread.startSyncObj.await();
97103
// Tell the worker thread to race to the exit and the
98-
// Thread.stop() calls will come in during thread exit.
104+
// JVM/TI StopThread() calls will come in during thread exit.
99105
thread.exitSyncObj.countDown();
100106
while (true) {
101-
thread.stop();
107+
retCode = stopThread(thread, myException);
108+
109+
if (retCode == JVMTI_ERROR_THREAD_NOT_ALIVE) {
110+
// Done with JVM/TI StopThread() calls since
111+
// thread is not alive.
112+
break;
113+
} else if (retCode != 0) {
114+
throw new RuntimeException("thread " + thread.getName()
115+
+ ": stopThread() " +
116+
"retCode=" + retCode +
117+
": unexpected value.");
118+
}
102119

103120
if (!thread.isAlive()) {
104-
// Done with Thread.stop() calls since
121+
// Done with JVM/TI StopThread() calls since
105122
// thread is not alive.
106123
break;
107124
}
108125
}
109126
} catch (InterruptedException e) {
110127
throw new Error("Unexpected: " + e);
111128
} catch (NoClassDefFoundError ncdfe) {
112-
// Ignore because we're testing Thread.stop() which can
129+
// Ignore because we're testing JVM/TI StopThread() which can
113130
// cause it. Yes, a NoClassDefFoundError that happens
114131
// in a worker thread can subsequently be seen in the
115132
// main thread.
@@ -120,9 +137,18 @@ public static void main(String[] args) {
120137
} catch (InterruptedException e) {
121138
throw new Error("Unexpected: " + e);
122139
}
123-
// This stop() call happens after the join() so it should do
124-
// nothing, but let's make sure.
125-
thread.stop();
140+
// This JVM/TI StopThread() happens after the join() so it
141+
// should do nothing, but let's make sure.
142+
retCode = stopThread(thread, myException);
143+
144+
if (retCode != JVMTI_ERROR_THREAD_NOT_ALIVE) {
145+
throw new RuntimeException("thread " + thread.getName()
146+
+ ": stopThread() " +
147+
"retCode=" + retCode +
148+
": unexpected value; " +
149+
"expected JVMTI_ERROR_THREAD_NOT_ALIVE(" +
150+
JVMTI_ERROR_THREAD_NOT_ALIVE + ").");
151+
}
126152

127153
if (myTG.activeCount() != 0) {
128154
// If the ThreadGroup still has a count, then the thread
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
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+
#include <string.h>
25+
#include "jvmti.h"
26+
27+
extern "C" {
28+
29+
static jvmtiEnv* jvmti = NULL;
30+
31+
#define LOG(...) \
32+
do { \
33+
printf(__VA_ARGS__); \
34+
printf("\n"); \
35+
fflush(stdout); \
36+
} while (0)
37+
38+
JNIEXPORT jint JNICALL
39+
Java_StopAtExit_stopThread(JNIEnv *jni, jclass cls, jthread thr, jobject exception) {
40+
return jvmti->StopThread(thr, exception);
41+
}
42+
43+
44+
/** Agent library initialization. */
45+
46+
JNIEXPORT jint JNICALL
47+
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
48+
LOG("\nAgent_OnLoad started");
49+
50+
// create JVMTI environment
51+
if (jvm->GetEnv((void **) (&jvmti), JVMTI_VERSION) != JNI_OK) {
52+
return JNI_ERR;
53+
}
54+
55+
// add specific capabilities for stoping thread
56+
jvmtiCapabilities stopCaps;
57+
memset(&stopCaps, 0, sizeof(stopCaps));
58+
stopCaps.can_signal_thread = 1;
59+
60+
jvmtiError err = jvmti->AddCapabilities(&stopCaps);
61+
if (err != JVMTI_ERROR_NONE) {
62+
return JNI_ERR;
63+
}
64+
LOG("Agent_OnLoad finished\n");
65+
return JNI_OK;
66+
}
67+
68+
}

0 commit comments

Comments
 (0)