Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4155645

"context class loader" doesn't work as intended (and is vaguely specified)

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Won't Fix
    • Icon: P4 P4
    • None
    • 1.2.0
    • core-libs
    • None

      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

            collins Gary Collins (Inactive)
            peterjones Peter Jones (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: