Skip to content

Commit 1abf971

Browse files
author
Alan Bateman
committed
8249627: Degrade Thread.suspend and Thread.resume
Reviewed-by: cjplummer, sspitsyn, dholmes, jpai
1 parent bc12e95 commit 1abf971

File tree

15 files changed

+113
-232
lines changed

15 files changed

+113
-232
lines changed

make/data/hotspot-symbols/symbols-unix

-2
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,6 @@ JVM_RegisterLambdaProxyClassForArchiving
194194
JVM_RegisterSignal
195195
JVM_ReleaseUTF
196196
JVM_ReportFinalizationComplete
197-
JVM_ResumeThread
198197
JVM_ExtentLocalCache
199198
JVM_SetExtentLocalCache
200199
JVM_SetArrayElement
@@ -207,7 +206,6 @@ JVM_Sleep
207206
JVM_StartThread
208207
JVM_StopThread
209208
JVM_SupportsCX8
210-
JVM_SuspendThread
211209
JVM_TotalMemory
212210
JVM_UnloadLibrary
213211
JVM_WaitForReferencePendingList

src/hotspot/share/include/jvm.h

-6
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,6 @@ JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
272272
JNIEXPORT jboolean JNICALL
273273
JVM_IsThreadAlive(JNIEnv *env, jobject thread);
274274

275-
JNIEXPORT void JNICALL
276-
JVM_SuspendThread(JNIEnv *env, jobject thread);
277-
278-
JNIEXPORT void JNICALL
279-
JVM_ResumeThread(JNIEnv *env, jobject thread);
280-
281275
JNIEXPORT void JNICALL
282276
JVM_SetThreadPriority(JNIEnv *env, jobject thread, jint prio);
283277

src/hotspot/share/prims/jvm.cpp

-23
Original file line numberDiff line numberDiff line change
@@ -3026,29 +3026,6 @@ JVM_ENTRY(jboolean, JVM_IsThreadAlive(JNIEnv* env, jobject jthread))
30263026
JVM_END
30273027

30283028

3029-
JVM_ENTRY(void, JVM_SuspendThread(JNIEnv* env, jobject jthread))
3030-
ThreadsListHandle tlh(thread);
3031-
JavaThread* receiver = NULL;
3032-
bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
3033-
if (is_alive) {
3034-
// jthread refers to a live JavaThread, but java_suspend() will
3035-
// detect a thread that has started to exit and will ignore it.
3036-
receiver->java_suspend();
3037-
}
3038-
JVM_END
3039-
3040-
3041-
JVM_ENTRY(void, JVM_ResumeThread(JNIEnv* env, jobject jthread))
3042-
ThreadsListHandle tlh(thread);
3043-
JavaThread* receiver = NULL;
3044-
bool is_alive = tlh.cv_internal_thread_to_JavaThread(jthread, &receiver, NULL);
3045-
if (is_alive) {
3046-
// jthread refers to a live JavaThread.
3047-
receiver->java_resume();
3048-
}
3049-
JVM_END
3050-
3051-
30523029
JVM_ENTRY(void, JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio))
30533030
ThreadsListHandle tlh(thread);
30543031
oop java_thread = NULL;

src/hotspot/share/prims/jvmti.xml

+4-8
Original file line numberDiff line numberDiff line change
@@ -1263,12 +1263,10 @@ jvmtiEnv *jvmti;
12631263
have this state flag set instead of <code>JVMTI_THREAD_STATE_SLEEPING</code>.
12641264
</constant>
12651265
<constant id="JVMTI_THREAD_STATE_SUSPENDED" num="0x100000">
1266-
Thread suspended.
1267-
<code>java.lang.Thread.suspend()</code>
1268-
or a <jvmti/> suspend function
1269-
(such as <functionlink id="SuspendThread"></functionlink>)
1270-
has been called on the thread. If this bit
1271-
is set, the other bits refer to the thread state before suspension.
1266+
Thread is suspended by a suspend function
1267+
(such as <functionlink id="SuspendThread"></functionlink>).
1268+
If this bit is set, the other bits refer to the thread state before
1269+
suspension.
12721270
</constant>
12731271
<constant id="JVMTI_THREAD_STATE_INTERRUPTED" num="0x200000">
12741272
Thread has been interrupted.
@@ -1780,7 +1778,6 @@ jvmtiEnv *jvmti;
17801778
Any threads currently suspended through
17811779
a <jvmti/> suspend function (eg.
17821780
<functionlink id="SuspendThread"></functionlink>)
1783-
or <code>java.lang.Thread.suspend()</code>
17841781
will resume execution;
17851782
all other threads are unaffected.
17861783
</description>
@@ -1815,7 +1812,6 @@ jvmtiEnv *jvmti;
18151812
Any thread suspended through
18161813
a <jvmti/> suspend function (eg.
18171814
<functionlink id="SuspendThreadList"></functionlink>)
1818-
or <code>java.lang.Thread.suspend()</code>
18191815
will resume execution.
18201816
</description>
18211817
<origin>jvmdi</origin>

src/java.base/share/classes/java/lang/IllegalThreadStateException.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,9 @@
2727

2828
/**
2929
* Thrown to indicate that a thread is not in an appropriate state
30-
* for the requested operation. See, for example, the
31-
* {@code suspend} and {@code resume} methods in class
32-
* {@code Thread}.
30+
* for the requested operation.
3331
*
34-
* @see java.lang.Thread#resume()
35-
* @see java.lang.Thread#suspend()
32+
* @see Thread#start()
3633
* @since 1.0
3734
*/
3835
public class IllegalThreadStateException extends IllegalArgumentException {

src/java.base/share/classes/java/lang/RuntimePermission.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -171,19 +171,16 @@
171171
* <tr>
172172
* <th scope="row">modifyThread</th>
173173
* <td>Modification of threads, e.g., via calls to Thread
174-
* {@code interrupt, stop, suspend, resume, setDaemon, setPriority,
175-
* setName} and {@code setUncaughtExceptionHandler}
176-
* methods</td>
174+
* {@code interrupt, setDaemon, setPriority, setName} and
175+
* {@code setUncaughtExceptionHandler} methods</td>
177176
* <td>This allows an attacker to modify the behaviour of
178177
* any thread in the system.</td>
179178
* </tr>
180179
*
181180
* <tr>
182181
* <th scope="row">modifyThreadGroup</th>
183182
* <td>modification of thread groups, e.g., via calls to ThreadGroup
184-
* {@code destroy}, {@code getParent}, {@code resume},
185-
* {@code setDaemon}, {@code setMaxPriority}, {@code stop},
186-
* and {@code suspend} methods</td>
183+
* {@code getParent}, {@code setDaemon}, and {@code setMaxPriority} methods</td>
187184
* <td>This allows an attacker to create thread groups and
188185
* set their run priority.</td>
189186
* </tr>

src/java.base/share/classes/java/lang/SecurityManager.java

+2-11
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,6 @@ private static ThreadGroup getRootGroup() {
494494
* calling thread is not allowed to modify the thread argument.
495495
* <p>
496496
* This method is invoked for the current security manager by the
497-
* {@code stop}, {@code suspend}, {@code resume},
498497
* {@code setPriority}, {@code setName}, and
499498
* {@code setDaemon} methods of class {@code Thread}.
500499
* <p>
@@ -523,12 +522,9 @@ private static ThreadGroup getRootGroup() {
523522
* permission to modify the thread.
524523
* @throws NullPointerException if the thread argument is
525524
* {@code null}.
526-
* @see java.lang.Thread#resume() resume
527525
* @see java.lang.Thread#setDaemon(boolean) setDaemon
528526
* @see java.lang.Thread#setName(java.lang.String) setName
529527
* @see java.lang.Thread#setPriority(int) setPriority
530-
* @see java.lang.Thread#stop() stop
531-
* @see java.lang.Thread#suspend() suspend
532528
* @see #checkPermission(java.security.Permission) checkPermission
533529
*/
534530
public void checkAccess(Thread t) {
@@ -547,9 +543,8 @@ public void checkAccess(Thread t) {
547543
* <p>
548544
* This method is invoked for the current security manager when a
549545
* new child thread or child thread group is created, and by the
550-
* {@code setDaemon}, {@code setMaxPriority},
551-
* {@code stop}, {@code suspend}, {@code resume}, and
552-
* {@code destroy} methods of class {@code ThreadGroup}.
546+
* {@code setDaemon} and {@code setMaxPriority} methods of class
547+
* {@code ThreadGroup}.
553548
* <p>
554549
* If the thread group argument is the system thread group (
555550
* has a {@code null} parent) then
@@ -576,12 +571,8 @@ public void checkAccess(Thread t) {
576571
* permission to modify the thread group.
577572
* @throws NullPointerException if the thread group argument is
578573
* {@code null}.
579-
* @see java.lang.ThreadGroup#destroy() destroy
580-
* @see java.lang.ThreadGroup#resume() resume
581574
* @see java.lang.ThreadGroup#setDaemon(boolean) setDaemon
582575
* @see java.lang.ThreadGroup#setMaxPriority(int) setMaxPriority
583-
* @see java.lang.ThreadGroup#stop() stop
584-
* @see java.lang.ThreadGroup#suspend() suspend
585576
* @see #checkPermission(java.security.Permission) checkPermission
586577
*/
587578
public void checkAccess(ThreadGroup g) {

src/java.base/share/classes/java/lang/Thread.java

+22-48
Original file line numberDiff line numberDiff line change
@@ -1798,65 +1798,41 @@ boolean alive() {
17981798
private native boolean isAlive0();
17991799

18001800
/**
1801-
* Suspends this thread.
1802-
* <p>
1803-
* First, the {@code checkAccess} method of this thread is called
1804-
* with no arguments. This may result in throwing a
1805-
* {@code SecurityException} (in the current thread).
1806-
* <p>
1807-
* If the thread is alive, it is suspended and makes no further
1808-
* progress unless and until it is resumed.
1809-
*
1810-
* @throws SecurityException if the current thread cannot modify
1811-
* this thread.
1812-
* @throws UnsupportedOperationException if invoked on a virtual thread
1813-
* @see #checkAccess
1814-
* @deprecated This method has been deprecated, as it is
1815-
* inherently deadlock-prone. If the target thread holds a lock on the
1816-
* monitor protecting a critical system resource when it is suspended, no
1817-
* thread can access this resource until the target thread is resumed. If
1818-
* the thread that would resume the target thread attempts to lock this
1819-
* monitor prior to calling {@code resume}, deadlock results. Such
1820-
* deadlocks typically manifest themselves as "frozen" processes.
1821-
* For more information, see
1822-
* <a href="{@docRoot}/java.base/java/lang/doc-files/threadPrimitiveDeprecation.html">Why
1823-
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
1801+
* Throws {@code UnsupportedOperationException}.
1802+
*
1803+
* @throws UnsupportedOperationException always
1804+
*
1805+
* @deprecated This method was originally specified to suspend a thread.
1806+
* It was inherently deadlock-prone. If the target thread held a lock on
1807+
* a monitor protecting a critical system resource when it was suspended,
1808+
* no thread could access the resource until the target thread was resumed.
1809+
* If the thread intending to resume the target thread attempted to lock
1810+
* the monitor prior to calling {@code resume}, deadlock would result.
1811+
* Such deadlocks typically manifested themselves as "frozen" processes.
1812+
* For more information, see
1813+
* <a href="{@docRoot}/java.base/java/lang/doc-files/threadPrimitiveDeprecation.html">Why
1814+
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
18241815
*/
18251816
@Deprecated(since="1.2", forRemoval=true)
18261817
public final void suspend() {
1827-
checkAccess();
1828-
if (isVirtual())
1829-
throw new UnsupportedOperationException();
1830-
suspend0();
1818+
throw new UnsupportedOperationException();
18311819
}
18321820

18331821
/**
1834-
* Resumes a suspended thread.
1835-
* <p>
1836-
* First, the {@code checkAccess} method of this thread is called
1837-
* with no arguments. This may result in throwing a
1838-
* {@code SecurityException} (in the current thread).
1839-
* <p>
1840-
* If the thread is alive but suspended, it is resumed and is
1841-
* permitted to make progress in its execution.
1822+
* Throws {@code UnsupportedOperationException}.
18421823
*
1843-
* @throws SecurityException if the current thread cannot modify this
1844-
* thread.
1845-
* @throws UnsupportedOperationException if invoked on a virtual thread
1846-
* @see #checkAccess
1847-
* @see #suspend()
1848-
* @deprecated This method exists solely for use with {@link #suspend},
1849-
* which has been deprecated because it is deadlock-prone.
1824+
* @throws UnsupportedOperationException always
1825+
*
1826+
* @deprecated This method was originally specified to resume a thread
1827+
* suspended with {@link #suspend()}. Suspending a thread was
1828+
* inherently deadlock-prone.
18501829
* For more information, see
18511830
* <a href="{@docRoot}/java.base/java/lang/doc-files/threadPrimitiveDeprecation.html">Why
18521831
* are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
18531832
*/
18541833
@Deprecated(since="1.2", forRemoval=true)
18551834
public final void resume() {
1856-
checkAccess();
1857-
if (isVirtual())
1858-
throw new UnsupportedOperationException();
1859-
resume0();
1835+
throw new UnsupportedOperationException();
18601836
}
18611837

18621838
/**
@@ -3035,8 +3011,6 @@ static void setHeadStackableScope(StackableScope scope) {
30353011

30363012
/* Some private helper methods */
30373013
private native void setPriority0(int newPriority);
3038-
private native void suspend0();
3039-
private native void resume0();
30403014
private native void interrupt0();
30413015
private static native void clearInterruptEvent();
30423016
private native void setNativeName(String name);

src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html

+8-7
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,14 @@ <h2>What if a thread doesn't respond to
160160
properly.</p>
161161
<hr>
162162
<h2>Why are <code>Thread.suspend</code> and
163-
<code>Thread.resume</code> deprecated?</h2>
164-
<p><code>Thread.suspend</code> is inherently deadlock-prone. If the
165-
target thread holds a lock on the monitor protecting a critical
166-
system resource when it is suspended, no thread can access this
167-
resource until the target thread is resumed. If the thread that
168-
would resume the target thread attempts to lock this monitor prior
169-
to calling <code>resume</code>, deadlock results. Such deadlocks
163+
<code>Thread.resume</code> deprecated and the ability to suspend or
164+
resume a thread removed?</h2>
165+
<p><code>Thread.suspend</code> was inherently deadlock-prone. If the
166+
target thread held a lock on a monitor protecting a critical
167+
system resource when it is suspended, no thread could access the
168+
resource until the target thread was resumed. If the thread intending
169+
to resume the target thread attempted to lock the monitor prior
170+
to calling <code>resume</code>, deadlock resulted. Such deadlocks
170171
typically manifest themselves as "frozen" processes.</p>
171172
<hr>
172173
<h2>What should I use instead of <code>Thread.suspend</code> and

src/java.base/share/native/libjava/Thread.c

-2
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
static JNINativeMethod methods[] = {
3939
{"start0", "()V", (void *)&JVM_StartThread},
4040
{"isAlive0", "()Z", (void *)&JVM_IsThreadAlive},
41-
{"suspend0", "()V", (void *)&JVM_SuspendThread},
42-
{"resume0", "()V", (void *)&JVM_ResumeThread},
4341
{"setPriority0", "(I)V", (void *)&JVM_SetThreadPriority},
4442
{"yield0", "()V", (void *)&JVM_Yield},
4543
{"sleep0", "(J)V", (void *)&JVM_Sleep},

src/java.se/share/data/jdwp/jdwp.spec

+7-12
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,7 @@ JDWP "Java(tm) Debug Wire Protocol"
182182
"Suspends the execution of the application running in the target "
183183
"VM. All Java threads currently running will be suspended. "
184184
"<p>"
185-
"Unlike java.lang.Thread.suspend, "
186-
"suspends of both the virtual machine and individual threads are "
185+
"Suspends of both the virtual machine and individual threads are "
187186
"counted. Before a thread will run again, it must be resumed through "
188187
"the <a href=\"#JDWP_VirtualMachine_Resume\">VM-level resume</a> command "
189188
"or the <a href=\"#JDWP_ThreadReference_Resume\">thread-level resume</a> command "
@@ -1835,21 +1834,17 @@ JDWP "Java(tm) Debug Wire Protocol"
18351834
(Command Suspend=2
18361835
"Suspends the thread. "
18371836
"<p>"
1838-
"Unlike java.lang.Thread.suspend(), suspends of both "
1839-
"the virtual machine and individual threads are counted. Before "
1840-
"a thread will run again, it must be resumed the same number "
1841-
"of times it has been suspended. "
1837+
"Suspends of both the virtual machine and individual threads are "
1838+
"counted. Before a thread will run again, it must be resumed the "
1839+
"same number of times it has been suspended. "
18421840
"<p>"
1843-
"Suspending single threads with command has the same "
1844-
"dangers java.lang.Thread.suspend(). If the suspended "
1845-
"thread holds a monitor needed by another running thread, "
1841+
"Suspending single threads is inherently deadlock-prone. If the "
1842+
"suspended thread holds a monitor needed by another running thread, "
18461843
"deadlock is possible in the target VM (at least until the "
18471844
"suspended thread is resumed again). "
18481845
"<p>"
18491846
"The suspended thread is guaranteed to remain suspended until "
1850-
"resumed through one of the JDI resume methods mentioned above; "
1851-
"the application in the target VM cannot resume the suspended thread "
1852-
"through {@link java.lang.Thread#resume}. "
1847+
"resumed through one of the JDI resume methods mentioned above. "
18531848
"<p>"
18541849
"Note that this doesn't change the status of the thread (see the "
18551850
"<a href=\"#JDWP_ThreadReference_Status\">ThreadStatus</a> command.) "

src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java

+12-12
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,21 @@ public interface ThreadReference extends ObjectReference {
7171
* {@link #resume} or resumed with other threads through
7272
* {@link VirtualMachine#resume}.
7373
* <p>
74-
* Unlike {@link java.lang.Thread#suspend},
75-
* suspends of both the virtual machine and individual threads are
74+
* Suspends of both the virtual machine and individual threads are
7675
* counted. Before a thread will run again, it must be resumed
77-
* (through {@link #resume} or {@link ThreadReference#resume})
76+
* (through {@link #resume} or {@link VirtualMachine#resume})
7877
* the same number of times it has been suspended.
7978
* <p>
80-
* Suspending single threads with this method has the same dangers
81-
* as {@link java.lang.Thread#suspend()}. If the suspended thread
82-
* holds a monitor needed by another running thread, deadlock is
83-
* possible in the target VM (at least until the suspended thread
79+
* Suspending single threads with this method is inherently deadlock-prone.
80+
* If the suspended thread holds a monitor needed by another running thread,
81+
* deadlock is possible in the target VM (at least until the suspended thread
8482
* is resumed again).
8583
* <p>
8684
* The suspended thread is guaranteed to remain suspended until
87-
* resumed through one of the JDI resume methods mentioned above;
88-
* the application in the target VM cannot resume the suspended thread
89-
* through {@link java.lang.Thread#resume}.
90-
* @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}.
85+
* resumed through one of the JDI resume methods mentioned above.
86+
*
87+
* @throws VMCannotBeModifiedException if the VirtualMachine is read-only
88+
* @see VirtualMachine#canBeModified()
9189
*/
9290
@SuppressWarnings("javadoc")
9391
void suspend();
@@ -101,7 +99,9 @@ public interface ThreadReference extends ObjectReference {
10199
* the thread will continue to execute.
102100
* Note: the normal way to resume from an event related suspension is
103101
* via {@link EventSet#resume}.
104-
* @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}.
102+
*
103+
* @throws VMCannotBeModifiedException if the VirtualMachine is read-only
104+
* @see VirtualMachine#canBeModified()
105105
*/
106106
void resume();
107107

0 commit comments

Comments
 (0)