java.security.AccessControlException
Thrown in stop()
, suspend()
, or resume()
Method of java.lang.Thread
When running an applet in a browser using the Sun Java Runtime Environment (JRE), a java.security.AccessControlException
is thrown in the stop
, suspend
, or resume
method of java.lang.Thread
class as shown in the following code:
java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThread)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at sun.applet.AppletSecurity.checkAccess(Unknown Source)
at java.lang.Thread.checkAccess(Unknown Source)
at java.lang.Thread.stop(Unknown Source)
at ....
The same applet runs without any error with the Microsoft Virtual Machine (VM).
This exception is caused when a user call these methods on a dead Thread
object in the Sun JRE.
The Java class libraries in the Sun JRE have changed over time. Some APIs have been clarified, some have been deprecated, and some have their implementation altered.
The result of calling stop
, suspend
, and resume
on a dead Thread
object was not well defined. In the Microsoft VM, they result in a no-op. However, in the Sun JRE, calling these methods on a dead Thread
object invalidates the underlying invariant expression of the implementation, thus resulting in an java.security.AccessControlException
.
The Thread
stop
, suspend
, and resume
methods are inherently unsafe and have been deprecated in the Java technology.
Replace calls to stop
, suspend
, and resume
with code that modifies a variable to indicate that the target thread should stop or suspend or resume.
The following examples show how your can replace stop, suspend and resume methods with the alternative code:
For example, assume that your applet contains the following methods:
private Thread blinker; public void start() { blinker = new Thread(this); blinker.start(); } public void stop() { blinker.stop(); // UNSAFE! }
public void destroy() { blinker.stop(); // UNSAFE and WILL throw java.security.AccessControlException in the Sun JRE! } public void run() { Thread thisThread = Thread.currentThread(); while (true) { try { thisThread.sleep(interval); } catch (InterruptedException e){ } repaint(); } }
You can avoid the use of blinker.stop
by modifying the applet's stop
, destroy,
and run
methods as shown in the following code:
private volatile Thread blinker; public void stop() { blinker = null; } public void destroy() { blinker = null; } public void run() { Thread thisThread = Thread.currentThread(); while (blinker == thisThread) { try { thisThread.sleep(interval); } catch (InterruptedException e){ } repaint(); } }
For example consider an applet that has the mousePressed
event handler which toggles the state of a thread called blinker
as shown in the following code:
private boolean threadSuspended; public void mousePressed(MouseEvent e) { e.consume(); if (threadSuspended) blinker.resume(); else blinker.suspend(); // DEADLOCK-PRONE! threadSuspended = !threadSuspended; } public void run() { while (true) { try { Thread.currentThread().sleep(interval); } catch (InterruptedException e){ } repaint(); }
You can avoid the use of blinker.suspend
and blinker.resume
by replacing the event handler with the following code:
private boolean volatile threadSuspended; public synchronized void mousePressed(MouseEvent e) { e.consume(); threadSuspended = !threadSuspended; if (!threadSuspended) notify(); } public void run() { while (true) { try { Thread.currentThread().sleep(interval); if (threadSuspended) { synchronized(this) { while (threadSuspended) wait(); } } } catch (InterruptedException e){ } repaint(); } }
Why Are Thread.stop
, Thread.suspend
, Thread.resume
, and Runtime.runFinalizersOnExit
Deprecated?