java.security.AccessControlException thrown ... (original) (raw)
java.security.AccessControlException
thrown in stop
, suspend
, or resume
method of java.lang.Thread
Symptoms
When running an applet in a browser using the Sun JRE, an
AccessControlException
is thrown in thestop
,suspend
, orresume
method ofjava.lang.Thread
.
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 under the Microsoft VM.
Cause
This exception is caused by calling 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 had their implementation altered.
The result of calling
stop
,suspend
, andresume
on a deadThread
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 deadThread
object invalidates the underlying invariant of the implementation, thus resulting in anAccessControlException
.
Resolution
The Thread
stop
, suspend
, and resume
methods are inherently unsafe and have been deprecated in the Java 2 platform.
To work around this problem, replace calls to stop
, suspend
, and resume
with code that simply modifies some variable to indicate that the target thread should stop/suspend/resume.
For example, suppose 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 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 Thread.stop
by replacing the applet's stop
, destroy,
and run
methods with:
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();
}
}
Another example: Suppose your applet contains the following mousePressed
event handler, which toggles the state of a thread called blinker
:
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 Thread.suspend
and Thread.resume
by replacing the event handler above with the following:
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();
}
}
Related Information
Why Are Thread.stop, Thread.suspend, Thread.resume, and Runtime.runFinalizersOnExit Deprecated?