From 661b8ba320378e0b5b5d34caa6da5c76d0c9f605 Mon Sep 17 00:00:00 2001 From: alanb Date: Tue, 11 Jun 2013 11:22:28 +0100 Subject: [PATCH] 7059085: Retire Thread.stop(Throwable) so that it throws UOE Reviewed-by: dholmes, chegar, forax, darcy, mduigou --- src/share/classes/java/lang/Thread.java | 81 ++++++------------------ test/java/lang/Thread/StopThrowable.java | 69 ++++++++++++++++++++ 2 files changed, 90 insertions(+), 60 deletions(-) create mode 100644 test/java/lang/Thread/StopThrowable.java diff --git a/src/share/classes/java/lang/Thread.java b/src/share/classes/java/lang/Thread.java index 81bebc58b..bb175ff89 100644 --- a/src/share/classes/java/lang/Thread.java +++ b/src/share/classes/java/lang/Thread.java @@ -812,68 +812,10 @@ class Thread implements Runnable { */ @Deprecated public final void stop() { - stop(new ThreadDeath()); - } - - /** - * Forces the thread to stop executing. - *

- * If there is a security manager installed, the checkAccess - * method of this thread is called, which may result in a - * 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) or - * obj is not an instance of ThreadDeath, the - * security manager's checkPermission method (with the - * RuntimePermission("stopThread") argument) is called in - * addition. - * Again, this may result in throwing a - * SecurityException (in the current thread). - *

- * If the argument obj is null, a - * NullPointerException is thrown (in the current thread). - *

- * The thread represented by this thread is forced to stop - * whatever it is doing abnormally and to throw the - * Throwable object obj as an exception. This - * is an unusual action to take; normally, the stop method - * that takes no arguments should be used. - *

- * It is permitted to stop a thread that has not yet been started. - * If the thread is eventually started, it immediately terminates. - * - * @param obj the Throwable object to be thrown. - * @exception SecurityException if the current thread cannot modify - * this thread. - * @throws NullPointerException if obj is null. - * @see #interrupt() - * @see #checkAccess() - * @see #run() - * @see #start() - * @see #stop() - * @see SecurityManager#checkAccess(Thread) - * @see SecurityManager#checkPermission - * @deprecated This method is inherently unsafe. See {@link #stop()} - * for details. An additional danger of this - * method is that it may be used to generate exceptions that the - * target thread is unprepared to handle (including checked - * exceptions that the thread could not possibly throw, were it - * not for this method). - * For more information, see - * Why - * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. - */ - @Deprecated - public final synchronized void stop(Throwable obj) { - if (obj == null) - throw new NullPointerException(); - SecurityManager security = System.getSecurityManager(); if (security != null) { checkAccess(); - if ((this != Thread.currentThread()) || - (!(obj instanceof ThreadDeath))) { + if (this != Thread.currentThread()) { security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION); } } @@ -884,7 +826,26 @@ class Thread implements Runnable { } // The VM can handle all thread states - stop0(obj); + stop0(new ThreadDeath()); + } + + /** + * Throws {@code UnsupportedOperationException}. + * + * @param obj ignored + * + * @deprecated This method was originally designed to force a thread to stop + * and throw a given {@code Throwable} as an exception. It was + * inherently unsafe (see {@link #stop()} for details), and furthermore + * could be used to generate exceptions that the target thread was + * not prepared to handle. + * For more information, see + * Why + * are Thread.stop, Thread.suspend and Thread.resume Deprecated?. + */ + @Deprecated + public final synchronized void stop(Throwable obj) { + throw new UnsupportedOperationException(); } /** diff --git a/test/java/lang/Thread/StopThrowable.java b/test/java/lang/Thread/StopThrowable.java new file mode 100644 index 000000000..edc3a8d50 --- /dev/null +++ b/test/java/lang/Thread/StopThrowable.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, 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 7059085 + * @summary Check that Thread.stop(Throwable) throws UOE + * @run testng StopThrowable + */ + +import org.testng.annotations.Test; + +import java.util.concurrent.CountDownLatch; + +public class StopThrowable { + + @Test(expectedExceptions=UnsupportedOperationException.class) + public void testStopSelf() { + Thread.currentThread().stop(new ThreadDeath()); + } + + private static void awaitUnchecked(CountDownLatch latch) { + try { + latch.await(); + } catch (InterruptedException e) { + // should not happen + throw new RuntimeException(e); + } + } + + @Test(expectedExceptions=UnsupportedOperationException.class) + public void testStopOther() throws Throwable { + CountDownLatch ready = new CountDownLatch(1); + CountDownLatch done = new CountDownLatch(1); + Thread t = new Thread( () -> { ready.countDown(); awaitUnchecked(done); } ); + t.start(); + try { + ready.await(); + t.stop(new ThreadDeath()); + } finally { + done.countDown(); + } + } + + @Test(expectedExceptions=UnsupportedOperationException.class) + public void testNull() { + Thread.currentThread().stop(null); + } +} -- GitLab