Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Explanation for thread creation problem in applet required

0 views
Skip to first unread message

Hendrik Wördehoff

unread,
Jul 23, 1999, 3:00:00 AM7/23/99
to
With Java 2 you are allowed to create new class loaders in applets with
URLClassLoader.newInstance(...). This could be quite useful to provide
some kind of "sandbox in the sandbox" context for some parts of the
applet.

But I get into trouble when the code loaded with the new class loader
tries to create a new thread. I get a
java.security.AccessControlException: access denied
(java.lang.RuntimePermission modifyThreadGroup ) when creating the new
thread from the event dispatch thread. I'll include some sample code
below.
On the other hand: I am allowed to create a new thread when calling the
same method from the original applet object.

Why am I not allowed to create threads in an object instantiated via a
new class loader?
Is there any solution or workaround for this problem from within the
applet?

Puzzled
Hendrik


And now for the sample code:

=== begin file Start.java ===
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class Start
extends Applet
implements ActionListener
{
Button button;
Component test;

public Start()
{
System.out.println("<init>");
}

public void init()
{
System.out.println("init");

setLayout(new FlowLayout());

button = new Button("Start");
button.setActionCommand("START");
button.addActionListener(this);
add(button);

test = null;
}

public void start()
{
System.out.println("start");
}

public void stop()
{
System.out.println("stop");
}

public void destroy()
{
System.out.println("destroy");

if ( test != null )
{
remove(test);
test = null;
}
remove(button);
button = null;
}


public void actionPerformed(ActionEvent event)
{
System.out.println("actionPerformed "+event);

if ( event.getActionCommand().equals("START") )
{
// remove old button
if ( test != null )
{
remove(test);
test = null;
invalidate();
validate();
}

// create new button (via a class loader)
// The action event from this button is used to try and
create
// a thread object from within the event dispatch thread.
try
{
ClassLoader cl = null;

if ( true )
{
// create new class loader
// A new object instantiated with this class loader
// is not allowed to create a new thread.

URLClassLoader ucl =
(URLClassLoader)this.getClass().getClassLoader();
System.out.println("original class loader "+ucl);

cl = URLClassLoader.newInstance(ucl.getURLs());
}
else
{
// use our standard class loader
// Everything works fine then.

cl = this.getClass().getClassLoader();
}
System.out.println("new class loader "+cl);

String classname = "Test";
Class c = cl.loadClass(classname);
Object o = c.newInstance();
test = (Component)o;
add(test);
System.out.println("neues Objekt "+test);
}
catch(Exception e) // especially ClassNotFoundException
{
System.out.println("Exception "+e);
}

invalidate();
validate();

// perform test
// The test works if it is called directly from this
execution context!
((ActionListener)test).actionPerformed(null);
}
}
}
=== end file Start.java ===
=== begin file Test.java ===
import java.awt.*;
import java.awt.event.*;

public class Test
extends Button
implements ActionListener
{
public Test()
{
super("Test");
addActionListener(this);

System.out.println("Test: <init>");

// this call succeeds
test();
}

public void actionPerformed(ActionEvent event)
{
System.out.println("Test: actionPerformed "+event);

// this call fails (if called from the event queue)
test();
}

/**
* The test method.
* It tries to create a new thread.
* This seems to work as long as it is triggered by an execution
path
* that contains an object created by the original class loader of
the
* applet.
* It fails if the execution path comes from the event thread.
*/
public void test()
{
System.out.println("Test: test");
System.out.println(" in thread "+Thread.currentThread());
System.out.println(" from class loader
"+this.getClass().getClassLoader());
Thread t = new Thread();
System.out.println(" succeeded");
}
}
=== end file Test.java ===

When compiling this with Java 2 SDK 1.2.2FCS on Windows NT and running
it in the applet viewer I get the following output (additional comments
added by me):

D:\>appletviewer Start.html
<init>
init
start
actionPerformed java.awt.event.ActionEvent[ACTION_PERFORMED,cmd=START]
on button0
original class loader sun.applet.AppletClassLoader@97889317
new class loader java.net.FactoryURLClassLoader@f489318
Test: <init>
// try to create thread from constructor of new object of class Test =>
OK
Test: test
in thread
Thread[AWT-EventQueue-0,4,file:/D:/java/work/StartApplet0/-threadGroup]
from class loader java.net.FactoryURLClassLoader@f489318
succeeded
neues Objekt Test[button1,0,0,0x0,invalid,label=Test]
Test: actionPerformed null
// call test method in new object from action listener of applet (class
Start) => OK
Test: test
in thread
Thread[AWT-EventQueue-0,4,file:/D:/java/work/StartApplet0/-threadGroup]
from class loader java.net.FactoryURLClassLoader@f489318
succeeded
Test: actionPerformed
java.awt.event.ActionEvent[ACTION_PERFORMED,cmd=Test] on button1
// call test method in new object from action listener => FAILS
Test: test
in thread
Thread[AWT-EventQueue-0,4,file:/D:/java/work/StartApplet0/-threadGroup]
from class loader java.net.FactoryURLClassLoader@f489318
Exception occurred during event dispatching:
java.security.AccessControlException: access denied
(java.lang.RuntimePermission modifyThr
eadGroup )
at
java.security.AccessControlContext.checkPermission(AccessControlContext.java:19
5)
at
java.security.AccessController.checkPermission(AccessController.java,
Compiled
Code)
at
java.lang.SecurityManager.checkPermission(SecurityManager.java, Compiled
Code)
at
sun.applet.AppletSecurity.checkAccess(AppletSecurity.java:143)
at java.lang.ThreadGroup.checkAccess(ThreadGroup.java:278)
at java.lang.Thread.init(Thread.java:263)
at java.lang.Thread.<init>(Thread.java:325)
at Test.test(Test.java:40)
at Test.actionPerformed(Test.java:24)
at java.awt.Button.processActionEvent(Button.java:308)
at java.awt.Button.processEvent(Button.java:281)
at java.awt.Component.dispatchEventImpl(Component.java:2394)
at java.awt.Component.dispatchEvent(Component.java:2307)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:287)
at
java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:101)
at
java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:92)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:83)

Pursuant to US Code, Title 47, Chapter 5, Subchapter II, Sec. 227,
any and all unsolicited commercial E-mail sent to this address
is subject to a download and archival fee in the amount of $500
US (per infraction). E-mailing denotes acceptance of these terms.

--
Hendrik Woerdehoff mailto:hendrik.w...@sdm.de
sd&m AG http://www.sdm.de
software design & management :
Thomas-Dehler-Str. 27, 81737 Muenchen, Germany >B)
Tel +49 89 63812-337 Fax -515 :

0 new messages