RFR: 8289610: Degrade Thread.stop [v4]

David Holmes dholmes at openjdk.org
Tue Sep 20 05:42:57 UTC 2022


On Sat, 17 Sep 2022 08:41:19 GMT, Alan Bateman <alanb at openjdk.org> wrote:

>> Degrade Thread.stop to throw UOE unconditionally, deprecate ThreadDeath for removal, and remove the remaining special handling of ThreadDeath from the JDK.
>> 
>> Thread.stop is inherently unsafe and has been deprecated since JDK 1.2 (1998) with a link to a supplementary page that explains the rationale. Some of the API surface has already been degraded or removed: Thread.stop(Throwable) was degraded to throw UOE in Java 8 and removed in Java 11, and ThreadGroup.stop was degraded to throw UOE in Java 19. As of Java 19, the no-arg Thread.stop continues to work as before for platform threads but throws UOE for virtual threads. The next step in the glacial pace removal is the degrading of the no-arg Thread.stop method to throw UOE for all threads.
>> 
>> To keep things manageable, the change proposed here leaves JVM_StopThread in place. A separate issue will remove it and do other cleanup/removal in the VM. We have another JBS issue for the updates to the JLS and JVMS where asynchronous exceptions are defined. There is also some remaining work on a test class used by 6 jshell tests - if they aren't done in time then we will temporarily exclude them.
>> 
>> The change here has no  impact on the debugger APIs (JVM TI StopThread, JDWP ThreadReference/Stop, and JDI ThreadReference.stop). Debuggers can continue to cause threads to throw an asynchronous exception, as might be done when simulating code throwing an exception at some point in the code.
>
> Alan Bateman has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains 12 additional commits since the last revision:
> 
>  - Merge
>  - Updates to Java Thread Primitive Deprecation page
>  - Repalce "it" with "victim thread"
>  - Merge
>  - Revert test/langtools/ProblemList.txt as jshell tests no longer rely on Thread.stop
>  - become -> became in javadoc
>  - Merge
>  - Remove stopThread permission from RuntimePermission table, exclude jshell tests
>  - Deprecate for removal
>  - Next iteration, update dates in headers
>  - ... and 2 more: https://git.openjdk.org/jdk/compare/4a31f682...93806f99

Hi Alan,

Good to see this finally become non-functional but as long as the debugger/JVMTI can trigger throwing an async ThreadDeath then I have to question the potential change in behaviour introduced by removing all the `catch (ThreadDeath td)` logic in various places.

src/java.base/share/classes/java/io/FilterOutputStream.java line 195:

> 193:                    // evaluate possible precedence of flushException over closeException
> 194:                    if ((flushException instanceof ThreadDeath) &&
> 195:                        !(closeException instanceof ThreadDeath)) {

If the ThreadDeath originates from the debugger then this is now a change in behaviour.

src/java.base/share/classes/java/lang/Shutdown.java line 132:

> 130:                 if (hook != null) hook.run();
> 131:             } catch (Throwable t) {
> 132:                 // ignore

Again change of behaviour if TD originates from debugger.

src/java.base/share/classes/java/lang/ThreadDeath.java line 30:

> 28: /**
> 29:  * An instance of {@code ThreadDeath} was originally specified to be thrown
> 30:  * by a victim thread when "stopped" with {@link Thread#stop()}.

Should this have always mentioned the possibility of TD coming from a debugger as well?

src/java.base/share/classes/java/lang/ThreadGroup.java line 700:

> 698:                 ueh.uncaughtException(t, e);
> 699:             } else {
> 700:                 System.err.print("Exception in thread \"" + t.getName() + "\" ");

Again change in behaviour.

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

> 35: stop a thread removed?</h2>
> 36: <p>Because it was inherently unsafe. Stopping a thread caused it to
> 37: unlock all the monitors that it had locked. (The monitors were

Just an aside but this rationale was always a significant under-statement as async-exceptions are inherently unsafe even if no concurrency or monitors are involved.

src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java line 170:

> 168:                     }
> 169:                 }
> 170:             } catch (ThreadDeath td) {

Again change in behaviour

src/java.desktop/share/classes/java/awt/EventDispatchThread.java line 205:

> 203:             eq.dispatchEvent(event);
> 204:         }
> 205:         catch (ThreadDeath death) {

Again change in behaviour.

-------------

PR: https://git.openjdk.org/jdk/pull/10230



More information about the client-libs-dev mailing list