diff --git a/src/java.base/share/classes/java/io/FilterOutputStream.java b/src/java.base/share/classes/java/io/FilterOutputStream.java index ca8604936c5..0be6e74901e 100644 --- a/src/java.base/share/classes/java/io/FilterOutputStream.java +++ b/src/java.base/share/classes/java/io/FilterOutputStream.java @@ -190,17 +190,9 @@ public class FilterOutputStream extends OutputStream { try { out.close(); } catch (Throwable closeException) { - // evaluate possible precedence of flushException over closeException - if ((flushException instanceof ThreadDeath) && - !(closeException instanceof ThreadDeath)) { - flushException.addSuppressed(closeException); - throw (ThreadDeath) flushException; - } - if (flushException != closeException) { closeException.addSuppressed(flushException); } - throw closeException; } } diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 6b1f8bddbd7..6b5d5412402 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -2430,8 +2430,6 @@ public class ObjectInputStream // Read fields of the current descriptor into a new FieldValues and discard new FieldValues(slotDesc, true); } else if (slotDesc.hasReadObjectMethod()) { - ThreadDeath t = null; - boolean reset = false; SerialCallbackContext oldContext = curContext; if (oldContext != null) oldContext.check(); @@ -2450,19 +2448,10 @@ public class ObjectInputStream */ handles.markException(passHandle, ex); } finally { - do { - try { - curContext.setUsed(); - if (oldContext!= null) - oldContext.check(); - curContext = oldContext; - reset = true; - } catch (ThreadDeath x) { - t = x; // defer until reset is true - } - } while (!reset); - if (t != null) - throw t; + curContext.setUsed(); + if (oldContext!= null) + oldContext.check(); + curContext = oldContext; } /* diff --git a/src/java.base/share/classes/java/lang/Error.java b/src/java.base/share/classes/java/lang/Error.java index 2992fabd069..e45b3f0e9f1 100644 --- a/src/java.base/share/classes/java/lang/Error.java +++ b/src/java.base/share/classes/java/lang/Error.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,6 @@ package java.lang; * An {@code Error} is a subclass of {@code Throwable} * that indicates serious problems that a reasonable application * should not try to catch. Most such errors are abnormal conditions. - * The {@code ThreadDeath} error, though a "normal" condition, - * is also a subclass of {@code Error} because most applications - * should not try to catch it. *
* A method is not required to declare in its {@code throws} * clause any subclasses of {@code Error} that might be thrown @@ -42,7 +39,6 @@ package java.lang; * exceptions for the purposes of compile-time checking of exceptions. * * @author Frank Yellin - * @see java.lang.ThreadDeath * @jls 11.2 Compile-Time Checking of Exceptions * @since 1.0 */ diff --git a/src/java.base/share/classes/java/lang/RuntimePermission.java b/src/java.base/share/classes/java/lang/RuntimePermission.java index 7df4c5fac5b..2d6ccdd5d1c 100644 --- a/src/java.base/share/classes/java/lang/RuntimePermission.java +++ b/src/java.base/share/classes/java/lang/RuntimePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -179,16 +179,6 @@ import java.lang.module.ModuleFinder; * * *
- * If there is a security manager installed, its {@code checkAccess} - * method is called with {@code this} - * as its argument. This may result in a - * {@code SecurityException} being raised (in the current thread). - *
- * If this thread is different from the current thread (that is, the current - * thread is trying to stop a thread other than itself), the - * security manager's {@code checkPermission} method (with a - * {@code RuntimePermission("stopThread")} argument) is called in - * addition. - * Again, this may result in throwing a - * {@code SecurityException} (in the current thread). - *
- * The thread represented by this thread is forced to stop whatever - * it is doing abnormally and to throw a newly created - * {@code ThreadDeath} object as an exception. - *
- * It is permitted to stop a thread that has not yet been started. - * If the thread is eventually started, it immediately terminates. - *
- * An application should not normally try to catch - * {@code ThreadDeath} unless it must do some extraordinary - * cleanup operation (note that the throwing of - * {@code ThreadDeath} causes {@code finally} clauses of - * {@code try} statements to be executed before the thread - * officially terminates). If a {@code catch} clause catches a - * {@code ThreadDeath} object, it is important to rethrow the - * object so that the thread actually terminates. - *
- * The top-level error handler that reacts to otherwise uncaught - * exceptions does not print out a message or otherwise notify the - * application if the uncaught exception is an instance of - * {@code ThreadDeath}. + * Throws {@code UnsupportedOperationException}. * - * @throws SecurityException if the current thread cannot - * modify this thread. - * @throws UnsupportedOperationException if invoked on a virtual thread - * @see #interrupt() - * @see #checkAccess() - * @see ThreadDeath - * @see ThreadGroup#uncaughtException(Thread,Throwable) - * @see SecurityManager#checkAccess(Thread) - * @see SecurityManager#checkPermission - * @deprecated This method is inherently unsafe. Stopping a thread with - * Thread.stop causes it to unlock all of the monitors that it - * has locked (as a natural consequence of the unchecked - * {@code ThreadDeath} exception propagating up the stack). If + * @throws UnsupportedOperationException always + * + * @deprecated This method was originally specified to "stop" a victim + * thread by causing the victim thread to throw a {@link ThreadDeath}. + * It was inherently unsafe. Stopping a thread caused it to unlock + * all of the monitors that it had locked (as a natural consequence + * of the {@code ThreadDeath} exception propagating up the stack). If * any of the objects previously protected by these monitors were in - * an inconsistent state, the damaged objects become visible to - * other threads, potentially resulting in arbitrary behavior. Many - * uses of {@code stop} should be replaced by code that simply + * an inconsistent state, the damaged objects became visible to + * other threads, potentially resulting in arbitrary behavior. + * Usages of {@code stop} should be replaced by code that simply * modifies some variable to indicate that the target thread should * stop running. The target thread should check this variable * regularly, and return from its run method in an orderly fashion @@ -1695,26 +1655,7 @@ public class Thread implements Runnable { */ @Deprecated(since="1.2", forRemoval=true) public final void stop() { - @SuppressWarnings("removal") - SecurityManager security = System.getSecurityManager(); - if (security != null) { - checkAccess(); - if (this != Thread.currentThread()) { - security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); - } - } - - if (isVirtual()) - throw new UnsupportedOperationException(); - - // A zero status value corresponds to "NEW", it can't change to - // not-NEW because we hold the lock. - if (holder.threadStatus != 0) { - resume(); // Wake up thread if it was suspended; no-op otherwise - } - - // The VM can handle all thread states - stop0(new ThreadDeath()); + throw new UnsupportedOperationException(); } /** @@ -3094,7 +3035,6 @@ public class Thread implements Runnable { /* Some private helper methods */ private native void setPriority0(int newPriority); - private native void stop0(Object o); private native void suspend0(); private native void resume0(); private native void interrupt0(); diff --git a/src/java.base/share/classes/java/lang/ThreadDeath.java b/src/java.base/share/classes/java/lang/ThreadDeath.java index 7d4e3ade1b4..743f1178abe 100644 --- a/src/java.base/share/classes/java/lang/ThreadDeath.java +++ b/src/java.base/share/classes/java/lang/ThreadDeath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,26 +26,19 @@ package java.lang; /** - * An instance of {@code ThreadDeath} is thrown in the victim thread - * when the (deprecated) {@link Thread#stop()} method is invoked. + * An instance of {@code ThreadDeath} was originally specified to be thrown + * by a victim thread when "stopped" with {@link Thread#stop()}. * - *
An application should catch instances of this class only if it - * must clean up after being terminated asynchronously. If - * {@code ThreadDeath} is caught by a method, it is important that it - * be rethrown so that the thread actually dies. - * - *
The {@linkplain ThreadGroup#uncaughtException top-level error - * handler} does not print out a message if {@code ThreadDeath} is - * never caught. - * - *
The class {@code ThreadDeath} is specifically a subclass of - * {@code Error} rather than {@code Exception}, even though it is a - * "normal occurrence", because many applications catch all - * occurrences of {@code Exception} and then discard the exception. + * @deprecated {@link Thread#stop()} was originally specified to "stop" a victim + * thread by causing the victim thread to throw a {@code ThreadDeath}. It + * was inherently unsafe and deprecated in an early JDK release. The ability + * to "stop" a thread with {@code Thread.stop} has been removed and the + * {@code Thread.stop} method changed to throw an exception. Consequently, + * {@code ThreadDeath} is also deprecated, for removal. * * @since 1.0 */ - +@Deprecated(since="20", forRemoval=true) public class ThreadDeath extends Error { @java.io.Serial private static final long serialVersionUID = -4417128565033088268L; diff --git a/src/java.base/share/classes/java/lang/ThreadGroup.java b/src/java.base/share/classes/java/lang/ThreadGroup.java index 9e57d921081..f6e278eb6d7 100644 --- a/src/java.base/share/classes/java/lang/ThreadGroup.java +++ b/src/java.base/share/classes/java/lang/ThreadGroup.java @@ -674,12 +674,9 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler { * uncaught exception handler} installed, and if so, its * {@code uncaughtException} method is called with the same * two arguments. - *