-
Bug
-
Resolution: Won't Fix
-
P4
-
None
-
1.2.0
-
None
-
sparc
-
solaris_2.5
A thread's context class loader is not always set how one would expect
it to be set, such as when callbacks are dispatched, making this new
feature useless in a lot of situations and causing class resolution to
fail when it should work. (Furthermore, these expectations of how the
context class loader should be getting set are based only on an
understanding of what this feature was intended for; the actual
specificification is extremely vague.)
A concrete example of the bug is that when applet code is invoked through
an AWT callback, the context class loader is NOT set to the applet's class
loader; thus, if the applet then tries to do anything that resolves classes
through the context class loader, it will fail. This behavior could be
considered an AWT bug, but it's not clear that it would be feasible or even
possible to fix AWT to set the context class loader correctly in all cases,
and this problem will apply to almost any other callback facility as well.
Therefore, perhaps we should consider that this bug is a design flaw in the
context class loader mechanism.
In addition, it is difficult for code to take matters into its own hands and
set the context class loader for a piece of code that it wishes to execute,
because modifying any thread's context class loader, even the current thread's
only during the current method's execution, requires the coarse-grained
"setContextClassLoader" permission (in 1.2beta3, it only required permission
to "access" the target thread).
[This bug report is being filed to document these couple of problems/issues
with the per-thread "context class loader" feature (of the 1.2 extension
mechanism) that have been discussed recently in several arenas, but no
resolution seems forthcoming.]
more details:
When an applet's code is executed, it should be able to expect that the
context class loader of the thread in which it was invoked will be the
class loader that loaded the applet. This applet-related support has
seemed to be the most concrete example given for the motiviation behind
the design of the current context class loader mechanism. The following
applet demonstrates how this expectation is not met (source files are
also attached to this bug report):
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class AppletContextClassLoader extends Applet {
public void init() {
outputContextLoader("init()");
Button b = new Button("Press Me");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
outputContextLoader("processActionEvent()");
}
});
this.add(b);
}
public void start() { outputContextLoader("start()"); }
public void stop() { outputContextLoader("stop()"); }
public void destroy() { outputContextLoader("destroy()"); }
private static void outputContextLoader(String where) {
ClassLoader contextLoader =
Thread.currentThread().getContextClassLoader();
System.err.println(where + ": context class loader = " + contextLoader);
}
}
When this applet is executed and the "Press Me" button is pressed, the
following output is printed to the console:
init(): context class loader = sun.applet.AppletClassLoader@7589d67d
start(): context class loader = sun.applet.AppletClassLoader@7589d67d
processActionEvent(): context class loader = sun.misc.Launcher$AppClassLoader@1301d67c
Notice that when the init() and start() methods are executed, the applet's
class loader is the context class loader, but when the handler for the
button press is executed, the context class loader is the "application"
class loader. (Note that this output required that the applet be granted
the "getClassLoader" permission, which is unusual; otherwise, the button
press would have resulted in a security exception!)
The methods called through the methods of java.applet.Applet do see the
context class loader properly set because our appletviewer implmentation
takes care to set the context class loader to the applet's class loader in
the thread that invokes those methods. But when applet code is invoked as
part of an AWT callback, the context class loader will just be the base loader
that loads classes from CLASSPATH; AWT doesn't do anything to set the
context class loader before calling back into the applet.
So is this a bug in AWT? Before making any callback, should it figure
out the context class loader for the component that it is calling into,
perhaps by remembering what the context class loader was when the event
listener was registered, and set it to that? Is this even possible (or
feasible to implement reliably) given the various layers of event
dispatch code? (I don't know.) Furthermore, is this a burden that we
want to place on all code that does event dispatching or other sorts of
callbacks? What about finalizers, for example?
Alternatively, is it responsibility of the callback code itself to set its
own context class loader? If this is true, then the other problem regarding
the coarse-grained permission required to set a context class loader is
particularly serious. For example, if applet code needs to set its own
context class loader, then it needs to be granted "setContextClassLoader"
permission, which should not be granted to arbitrary applets...
The other problem is that the facility is strongly limited by the overly
coarse-grained permission required to set one's thread's context class loader.
In 1.2beta3, only "access" to the target thread was required to set its
context class loader. Perhaps this was too lenient, but now with 1.2beta4,
the "setContextClassLoader" RuntimePermission is required to modify *any*
thread's context class loader, so code can't even set the context loader for
the current thread. I presume that the (quite sensible) worry is that without
some security check, any code could code change the context class loader of its
caller, which is bad because how could the caller ever be prepared for the
ramifications of that occurrence. But there is no problem with an arbitrary
method setting its thread's context class loader just for the duration of its
execution, which is exactly all that most code will want to do, i.e.
something like this:
(ignoring for the moment that try/finally is now deemed unreliable...)
ClassLoader savedCcl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(otherLoader);
// do some stuff in context of "otherLoader" ...
} finally {
Thread.currentThread().setContextClassLoader(savedCcl);
}
But we can't grant not-fully-trusted code the ability to set the context class
loader only for its own needs like this without giving it the ability to mess
up its caller's context, so any code that wants to set the context class loader
will need to need to require that it be granted "setContextClassLoader"
permission, which is a lot of trust to require, especially if no other explicit
permissions are otherwise necessary to grant to it.
Some real complaints about the difficulty with this coarse-grained
"setContextClassLoader" permission have been reported on 1.2 RMI applications
in development that want to supply downloadable proxy classes that need to
deserialize a MarhsalledObject received from a remote server using a
particular class loader to resolve classes from, and this class loader is
not the context class loader, nor is it even on the execution stack. So the
context class loader needs to be set during the harmless operation, but the
dangerous "setContextClassLoader" permission is required.
peter.jones@East 1998-07-08
it to be set, such as when callbacks are dispatched, making this new
feature useless in a lot of situations and causing class resolution to
fail when it should work. (Furthermore, these expectations of how the
context class loader should be getting set are based only on an
understanding of what this feature was intended for; the actual
specificification is extremely vague.)
A concrete example of the bug is that when applet code is invoked through
an AWT callback, the context class loader is NOT set to the applet's class
loader; thus, if the applet then tries to do anything that resolves classes
through the context class loader, it will fail. This behavior could be
considered an AWT bug, but it's not clear that it would be feasible or even
possible to fix AWT to set the context class loader correctly in all cases,
and this problem will apply to almost any other callback facility as well.
Therefore, perhaps we should consider that this bug is a design flaw in the
context class loader mechanism.
In addition, it is difficult for code to take matters into its own hands and
set the context class loader for a piece of code that it wishes to execute,
because modifying any thread's context class loader, even the current thread's
only during the current method's execution, requires the coarse-grained
"setContextClassLoader" permission (in 1.2beta3, it only required permission
to "access" the target thread).
[This bug report is being filed to document these couple of problems/issues
with the per-thread "context class loader" feature (of the 1.2 extension
mechanism) that have been discussed recently in several arenas, but no
resolution seems forthcoming.]
more details:
When an applet's code is executed, it should be able to expect that the
context class loader of the thread in which it was invoked will be the
class loader that loaded the applet. This applet-related support has
seemed to be the most concrete example given for the motiviation behind
the design of the current context class loader mechanism. The following
applet demonstrates how this expectation is not met (source files are
also attached to this bug report):
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class AppletContextClassLoader extends Applet {
public void init() {
outputContextLoader("init()");
Button b = new Button("Press Me");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
outputContextLoader("processActionEvent()");
}
});
this.add(b);
}
public void start() { outputContextLoader("start()"); }
public void stop() { outputContextLoader("stop()"); }
public void destroy() { outputContextLoader("destroy()"); }
private static void outputContextLoader(String where) {
ClassLoader contextLoader =
Thread.currentThread().getContextClassLoader();
System.err.println(where + ": context class loader = " + contextLoader);
}
}
When this applet is executed and the "Press Me" button is pressed, the
following output is printed to the console:
init(): context class loader = sun.applet.AppletClassLoader@7589d67d
start(): context class loader = sun.applet.AppletClassLoader@7589d67d
processActionEvent(): context class loader = sun.misc.Launcher$AppClassLoader@1301d67c
Notice that when the init() and start() methods are executed, the applet's
class loader is the context class loader, but when the handler for the
button press is executed, the context class loader is the "application"
class loader. (Note that this output required that the applet be granted
the "getClassLoader" permission, which is unusual; otherwise, the button
press would have resulted in a security exception!)
The methods called through the methods of java.applet.Applet do see the
context class loader properly set because our appletviewer implmentation
takes care to set the context class loader to the applet's class loader in
the thread that invokes those methods. But when applet code is invoked as
part of an AWT callback, the context class loader will just be the base loader
that loads classes from CLASSPATH; AWT doesn't do anything to set the
context class loader before calling back into the applet.
So is this a bug in AWT? Before making any callback, should it figure
out the context class loader for the component that it is calling into,
perhaps by remembering what the context class loader was when the event
listener was registered, and set it to that? Is this even possible (or
feasible to implement reliably) given the various layers of event
dispatch code? (I don't know.) Furthermore, is this a burden that we
want to place on all code that does event dispatching or other sorts of
callbacks? What about finalizers, for example?
Alternatively, is it responsibility of the callback code itself to set its
own context class loader? If this is true, then the other problem regarding
the coarse-grained permission required to set a context class loader is
particularly serious. For example, if applet code needs to set its own
context class loader, then it needs to be granted "setContextClassLoader"
permission, which should not be granted to arbitrary applets...
The other problem is that the facility is strongly limited by the overly
coarse-grained permission required to set one's thread's context class loader.
In 1.2beta3, only "access" to the target thread was required to set its
context class loader. Perhaps this was too lenient, but now with 1.2beta4,
the "setContextClassLoader" RuntimePermission is required to modify *any*
thread's context class loader, so code can't even set the context loader for
the current thread. I presume that the (quite sensible) worry is that without
some security check, any code could code change the context class loader of its
caller, which is bad because how could the caller ever be prepared for the
ramifications of that occurrence. But there is no problem with an arbitrary
method setting its thread's context class loader just for the duration of its
execution, which is exactly all that most code will want to do, i.e.
something like this:
(ignoring for the moment that try/finally is now deemed unreliable...)
ClassLoader savedCcl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(otherLoader);
// do some stuff in context of "otherLoader" ...
} finally {
Thread.currentThread().setContextClassLoader(savedCcl);
}
But we can't grant not-fully-trusted code the ability to set the context class
loader only for its own needs like this without giving it the ability to mess
up its caller's context, so any code that wants to set the context class loader
will need to need to require that it be granted "setContextClassLoader"
permission, which is a lot of trust to require, especially if no other explicit
permissions are otherwise necessary to grant to it.
Some real complaints about the difficulty with this coarse-grained
"setContextClassLoader" permission have been reported on 1.2 RMI applications
in development that want to supply downloadable proxy classes that need to
deserialize a MarhsalledObject received from a remote server using a
particular class loader to resolve classes from, and this class loader is
not the context class loader, nor is it even on the execution stack. So the
context class loader needs to be set during the harmless operation, but the
dangerous "setContextClassLoader" permission is required.
peter.jones@East 1998-07-08
- relates to
-
JDK-4171278 unreferenced callback should set context class loader before invoking user code
-
- Closed
-
-
JDK-4267872 Context class loader of event dispatch threads is being set incorrectly
-
- Closed
-
-
JDK-4279803 JNDI can't find LdapCtxFactory in 1.2.2 the previous version worked
-
- Closed
-