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 :