8289610: Degrade Thread.stop
Reviewed-by: rriggs, cjplummer, jpai, mchung, prr, mullan
This commit is contained in:
parent
05c8cabdad
commit
acd5bcfc88
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* 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
|
||||
*/
|
||||
|
@ -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;
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <th scope="row">stopThread</th>
|
||||
* <td>Stopping of threads via calls to the Thread {@code stop}
|
||||
* method</td>
|
||||
* <td>This allows code to stop any thread in the system provided that it is
|
||||
* already granted permission to access that thread.
|
||||
* This poses as a threat, because that code may corrupt the system by
|
||||
* killing existing threads.</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <th scope="row">modifyThreadGroup</th>
|
||||
* <td>modification of thread groups, e.g., via calls to ThreadGroup
|
||||
* {@code destroy}, {@code getParent}, {@code resume},
|
||||
|
@ -129,9 +129,7 @@ class Shutdown {
|
||||
}
|
||||
if (hook != null) hook.run();
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof ThreadDeath td) {
|
||||
throw td;
|
||||
}
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1629,59 +1629,19 @@ public class Thread implements Runnable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the thread to stop executing.
|
||||
* <p>
|
||||
* 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).
|
||||
* <p>
|
||||
* 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).
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* It is permitted to stop a thread that has not yet been started.
|
||||
* If the thread is eventually started, it immediately terminates.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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();
|
||||
|
@ -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()}.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>The {@linkplain ThreadGroup#uncaughtException top-level error
|
||||
* handler} does not print out a message if {@code ThreadDeath} is
|
||||
* never caught.
|
||||
*
|
||||
* <p>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;
|
||||
|
@ -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.
|
||||
* <li>Otherwise, this method determines if the {@code Throwable}
|
||||
* argument is an instance of {@link ThreadDeath}. If so, nothing
|
||||
* special is done. Otherwise, a message containing the
|
||||
* thread's name, as returned from the thread's {@link
|
||||
* Thread#getName getName} method, and a stack backtrace,
|
||||
* using the {@code Throwable}'s {@link
|
||||
* <li>Otherwise, a message containing the thread's name, as returned
|
||||
* from the thread's {@link Thread#getName getName} method, and a
|
||||
* stack backtrace, using the {@code Throwable}'s {@link
|
||||
* Throwable#printStackTrace() printStackTrace} method, is
|
||||
* printed to the {@linkplain System#err standard error stream}.
|
||||
* </ul>
|
||||
@ -699,9 +696,8 @@ public class ThreadGroup implements Thread.UncaughtExceptionHandler {
|
||||
Thread.getDefaultUncaughtExceptionHandler();
|
||||
if (ueh != null) {
|
||||
ueh.uncaughtException(t, e);
|
||||
} else if (!(e instanceof ThreadDeath)) {
|
||||
System.err.print("Exception in thread \""
|
||||
+ t.getName() + "\" ");
|
||||
} else {
|
||||
System.err.print("Exception in thread \"" + t.getName() + "\" ");
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2005, 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
|
||||
@ -31,31 +31,32 @@
|
||||
<body>
|
||||
<h1>Java Thread Primitive Deprecation</h1>
|
||||
<hr>
|
||||
<h2>Why is <code>Thread.stop</code> deprecated?</h2>
|
||||
<p>Because it is inherently unsafe. Stopping a thread causes it to
|
||||
unlock all the monitors that it has locked. (The monitors are
|
||||
unlocked as the <code>ThreadDeath</code> exception propagates up
|
||||
<h2>Why is <code>Thread.stop</code> deprecated and the ability to
|
||||
stop a thread removed?</h2>
|
||||
<p>Because it was inherently unsafe. Stopping a thread caused it to
|
||||
unlock all the monitors that it had locked. (The monitors were
|
||||
unlocked as the <code>ThreadDeath</code> exception propagated up
|
||||
the stack.) If any of the objects previously protected by these
|
||||
monitors were in an inconsistent state, other threads may now view
|
||||
monitors were in an inconsistent state, other threads may have viewed
|
||||
these objects in an inconsistent state. Such objects are said to be
|
||||
<i>damaged</i>. When threads operate on damaged objects, arbitrary
|
||||
behavior can result. This behavior may be subtle and difficult to
|
||||
detect, or it may be pronounced. Unlike other unchecked exceptions,
|
||||
<code>ThreadDeath</code> kills threads silently; thus, the user has
|
||||
no warning that his program may be corrupted. The corruption can
|
||||
<code>ThreadDeath</code> killed threads silently; thus, the user had
|
||||
no warning that their program may be corrupted. The corruption could
|
||||
manifest itself at any time after the actual damage occurs, even
|
||||
hours or days in the future.</p>
|
||||
<hr>
|
||||
<h2>Couldn't I just catch the <code>ThreadDeath</code> exception
|
||||
and fix the damaged object?</h2>
|
||||
<h2>Couldn't I have just caught <code>ThreadDeath</code> and fixed
|
||||
the damaged object?</h2>
|
||||
<p>In theory, perhaps, but it would <em>vastly</em> complicate the
|
||||
task of writing correct multithreaded code. The task would be
|
||||
nearly insurmountable for two reasons:</p>
|
||||
<ol>
|
||||
<li>A thread can throw a <code>ThreadDeath</code> exception
|
||||
<li>A thread could throw a <code>ThreadDeath</code> exception
|
||||
<i>almost anywhere</i>. All synchronized methods and blocks would
|
||||
have to be studied in great detail, with this in mind.</li>
|
||||
<li>A thread can throw a second <code>ThreadDeath</code> exception
|
||||
<li>A thread could throw a second <code>ThreadDeath</code> exception
|
||||
while cleaning up from the first (in the <code>catch</code> or
|
||||
<code>finally</code> clause). Cleanup would have to be repeated till
|
||||
it succeeded. The code to ensure this would be quite complex.</li>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 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
|
||||
@ -178,7 +178,7 @@ final class BootstrapMethodInvoker {
|
||||
catch (Error e) {
|
||||
// Pass through an Error, including BootstrapMethodError, any other
|
||||
// form of linkage error, such as IllegalAccessError if the bootstrap
|
||||
// method is inaccessible, or say ThreadDeath/OutOfMemoryError
|
||||
// method is inaccessible, or say OutOfMemoryError
|
||||
// See the "Linking Exceptions" section for the invokedynamic
|
||||
// instruction in JVMS 6.5.
|
||||
throw e;
|
||||
|
@ -335,7 +335,7 @@ abstract sealed class CallSite permits ConstantCallSite, MutableCallSite, Volati
|
||||
} catch (Error e) {
|
||||
// Pass through an Error, including BootstrapMethodError, any other
|
||||
// form of linkage error, such as IllegalAccessError if the bootstrap
|
||||
// method is inaccessible, or say ThreadDeath/OutOfMemoryError
|
||||
// method is inaccessible, or say OutOfMemoryError
|
||||
// See the "Linking Exceptions" section for the invokedynamic
|
||||
// instruction in JVMS 6.5.
|
||||
throw e;
|
||||
|
@ -124,10 +124,6 @@ public final class SecurityConstants {
|
||||
public static final RuntimePermission GET_CLASSLOADER_PERMISSION =
|
||||
new RuntimePermission("getClassLoader");
|
||||
|
||||
// java.lang.Thread
|
||||
public static final RuntimePermission STOP_THREAD_PERMISSION =
|
||||
new RuntimePermission("stopThread");
|
||||
|
||||
// java.lang.Thread
|
||||
public static final RuntimePermission GET_STACK_TRACE_PERMISSION =
|
||||
new RuntimePermission("getStackTrace");
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
{"start0", "()V", (void *)&JVM_StartThread},
|
||||
{"stop0", "(" OBJ ")V", (void *)&JVM_StopThread},
|
||||
{"isAlive0", "()Z", (void *)&JVM_IsThreadAlive},
|
||||
{"suspend0", "()V", (void *)&JVM_SuspendThread},
|
||||
{"resume0", "()V", (void *)&JVM_ResumeThread},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -167,11 +167,6 @@ public abstract class LWToolkit extends SunToolkit implements Runnable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (ThreadDeath td) {
|
||||
//XXX: if there isn't native code on the stack, the VM just
|
||||
//kills the thread right away. Do we expect to catch it
|
||||
//nevertheless?
|
||||
break;
|
||||
} catch (Throwable t) {
|
||||
// TODO: log
|
||||
System.err.println("Exception on the toolkit thread");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 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
|
||||
@ -202,10 +202,6 @@ class EventDispatchThread extends Thread {
|
||||
|
||||
eq.dispatchEvent(event);
|
||||
}
|
||||
catch (ThreadDeath death) {
|
||||
doDispatch = false;
|
||||
throw death;
|
||||
}
|
||||
catch (InterruptedException interruptedException) {
|
||||
doDispatch = false; // AppContext.dispose() interrupts all
|
||||
// Threads in the AppContext
|
||||
|
@ -198,13 +198,6 @@ class TimerQueue implements Runnable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ThreadDeath td) {
|
||||
// Mark all the timers we contain as not being queued.
|
||||
for (DelayedTimer delayedTimer : queue) {
|
||||
delayedTimer.getTimer().cancelEvent();
|
||||
}
|
||||
throw td;
|
||||
} finally {
|
||||
running = false;
|
||||
runningLock.unlock();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -2386,11 +2386,6 @@ class Parser implements DTDConstants {
|
||||
errorContext();
|
||||
error("exception", e.getClass().getName(), e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (ThreadDeath e) {
|
||||
errorContext();
|
||||
error("terminated");
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
} finally {
|
||||
for (; stack != null ; stack = stack.next) {
|
||||
handleEndTag(stack.tag);
|
||||
|
@ -727,9 +727,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
|
||||
}
|
||||
|
||||
dispatchEvent(ev);
|
||||
} catch (ThreadDeath td) {
|
||||
XBaseWindow.ungrabInput();
|
||||
return;
|
||||
} catch (Throwable thr) {
|
||||
XBaseWindow.ungrabInput();
|
||||
processException(thr);
|
||||
@ -1994,8 +1991,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
|
||||
|
||||
try {
|
||||
task.run();
|
||||
} catch (ThreadDeath td) {
|
||||
throw td;
|
||||
} catch (Throwable thr) {
|
||||
processException(thr);
|
||||
}
|
||||
|
@ -2666,8 +2666,6 @@ public class LogManager {
|
||||
for (Runnable c : listeners.values().toArray(new Runnable[0])) {
|
||||
try {
|
||||
c.run();
|
||||
} catch (ThreadDeath death) {
|
||||
throw death;
|
||||
} catch (Error | RuntimeException x) {
|
||||
if (t == null) t = x;
|
||||
else t.addSuppressed(x);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@ -1030,7 +1030,7 @@ public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
|
||||
try {
|
||||
return doc.getXmlVersion();
|
||||
} // The VM ran out of memory or there was some other serious problem. Re-throw.
|
||||
catch (VirtualMachineError | ThreadDeath vme) {
|
||||
catch (VirtualMachineError vme) {
|
||||
throw vme;
|
||||
} // Ignore all other exceptions and errors
|
||||
catch (Throwable t) {
|
||||
@ -1046,7 +1046,7 @@ public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
|
||||
try {
|
||||
return doc.getInputEncoding();
|
||||
} // The VM ran out of memory or there was some other serious problem. Re-throw.
|
||||
catch (VirtualMachineError | ThreadDeath vme) {
|
||||
catch (VirtualMachineError vme) {
|
||||
throw vme;
|
||||
} // Ignore all other exceptions and errors
|
||||
catch (Throwable t) {
|
||||
@ -1062,7 +1062,7 @@ public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
|
||||
try {
|
||||
return doc.getXmlEncoding();
|
||||
} // The VM ran out of memory or there was some other serious problem. Re-throw.
|
||||
catch (VirtualMachineError | ThreadDeath vme) {
|
||||
catch (VirtualMachineError vme) {
|
||||
throw vme;
|
||||
} // Ignore all other exceptions and errors
|
||||
catch (Throwable t) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -261,10 +261,6 @@ public abstract class AttachProvider {
|
||||
try {
|
||||
providers.add(i.next());
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof ThreadDeath) {
|
||||
ThreadDeath td = (ThreadDeath)t;
|
||||
throw td;
|
||||
}
|
||||
// Log errors and exceptions since we cannot return them
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 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
|
||||
@ -75,9 +75,6 @@ public abstract class HotSpotAttachProvider extends AttachProvider {
|
||||
if (t instanceof ExceptionInInitializerError) {
|
||||
t = t.getCause();
|
||||
}
|
||||
if (t instanceof ThreadDeath) {
|
||||
throw (ThreadDeath)t;
|
||||
}
|
||||
if (t instanceof SecurityException) {
|
||||
return result;
|
||||
}
|
||||
@ -101,9 +98,7 @@ public abstract class HotSpotAttachProvider extends AttachProvider {
|
||||
result.add(new HotSpotVirtualMachineDescriptor(this, pid, name));
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof ThreadDeath) {
|
||||
throw (ThreadDeath)t;
|
||||
}
|
||||
// ignore
|
||||
} finally {
|
||||
if (mvm != null) {
|
||||
mvm.detach();
|
||||
@ -138,10 +133,6 @@ public abstract class HotSpotAttachProvider extends AttachProvider {
|
||||
return;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (t instanceof ThreadDeath) {
|
||||
ThreadDeath td = (ThreadDeath)t;
|
||||
throw td;
|
||||
}
|
||||
// we do not know what this id is
|
||||
return;
|
||||
} finally {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -99,12 +99,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManagerService {
|
||||
|
||||
try {
|
||||
connector = connectors.next();
|
||||
} catch (ThreadDeath x) {
|
||||
throw x;
|
||||
} catch (Exception x) {
|
||||
System.err.println(x);
|
||||
continue;
|
||||
} catch (Error x) {
|
||||
} catch (Exception | Error x) {
|
||||
System.err.println(x);
|
||||
continue;
|
||||
}
|
||||
@ -128,12 +123,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManagerService {
|
||||
|
||||
try {
|
||||
transportService = transportServices.next();
|
||||
} catch (ThreadDeath x) {
|
||||
throw x;
|
||||
} catch (Exception x) {
|
||||
System.err.println(x);
|
||||
continue;
|
||||
} catch (Error x) {
|
||||
} catch (Exception | Error x) {
|
||||
System.err.println(x);
|
||||
continue;
|
||||
}
|
||||
|
@ -114,6 +114,7 @@ public class LocalExecutionControl extends DirectExecutionControl {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
protected String invoke(Method doitMethod) throws Exception {
|
||||
if (allStop == null) {
|
||||
super.load(new ClassBytecodes[]{ genCancelClass() });
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 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
|
||||
@ -160,7 +160,7 @@ public class RemoteExecutionControl extends DirectExecutionControl implements Ex
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial") // serialVersionUID intentionally omitted
|
||||
@SuppressWarnings({"serial", "removal"}) // serialVersionUID intentionally omitted
|
||||
private class StopExecutionException extends ThreadDeath {
|
||||
|
||||
@Override
|
||||
|
113
test/jdk/java/lang/Thread/StopTest.java
Normal file
113
test/jdk/java/lang/Thread/StopTest.java
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8289610
|
||||
* @summary Test Thread.stop throws UnsupportedOperationException
|
||||
* @run testng StopTest
|
||||
*/
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
public class StopTest {
|
||||
|
||||
/**
|
||||
* Test stop on the current thread.
|
||||
*/
|
||||
@Test
|
||||
public void testCurrentThread() {
|
||||
var thread = Thread.currentThread();
|
||||
assertThrows(UnsupportedOperationException.class, thread::stop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test stop on an unstarted thread.
|
||||
*/
|
||||
@Test
|
||||
public void testUnstartedThread() {
|
||||
Thread thread = new Thread(() -> { });
|
||||
assertThrows(UnsupportedOperationException.class, thread::stop);
|
||||
assertTrue(thread.getState() == Thread.State.NEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test stop on a thread spinning in a loop.
|
||||
*/
|
||||
@Test
|
||||
public void testRunnableThread() throws Exception {
|
||||
AtomicBoolean done = new AtomicBoolean();
|
||||
Thread thread = new Thread(() -> {
|
||||
while (!done.get()) {
|
||||
Thread.onSpinWait();
|
||||
}
|
||||
});
|
||||
thread.start();
|
||||
try {
|
||||
assertThrows(UnsupportedOperationException.class, thread::stop);
|
||||
|
||||
// thread should not terminate
|
||||
boolean terminated = thread.join(Duration.ofMillis(500));
|
||||
assertFalse(terminated);
|
||||
} finally {
|
||||
done.set(true);
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test stop on a thread that is parked.
|
||||
*/
|
||||
@Test
|
||||
public void testWaitingThread() throws Exception {
|
||||
Thread thread = new Thread(LockSupport::park);
|
||||
thread.start();
|
||||
try {
|
||||
// wait for thread to park
|
||||
while ((thread.getState() != Thread.State.WAITING)) {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
assertThrows(UnsupportedOperationException.class, thread::stop);
|
||||
assertTrue(thread.getState() == Thread.State.WAITING);
|
||||
} finally {
|
||||
LockSupport.unpark(thread);
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test stop on a terminated thread.
|
||||
*/
|
||||
@Test
|
||||
public void testTerminatedThread() throws Exception {
|
||||
Thread thread = new Thread(() -> { });
|
||||
thread.start();
|
||||
thread.join();
|
||||
assertThrows(UnsupportedOperationException.class, thread::stop);
|
||||
assertTrue(thread.getState() == Thread.State.TERMINATED);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user