jakarta-bsf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Rony G. Flatscher" <Rony.Flatsc...@wu-wien.ac.at>
Subject Issue with ClassLoaders ...
Date Thu, 20 Sep 2007 10:24:29 GMT
Hi there,

about two weeks ago I downloaded OpenOffice 2.3.0 (OOo), release
candidate 2, to test BSF4Rexx, which enables the ooRexx scripting
language to interface/script/remote-control OpenOffice via its Java
APIs. OOo is mostly implemented in C++, but has a full set of Java APIs
to it. Also, OOo has a Java written Scripting framework via which one
can deploy any of the BSF supported scriping engines. It is in this area
(allowing a scripting language to be deployed as a macro language by OOo
itself), where a class loader problem has surfaced, now that OOo uses a
customized class loader to load OOo extensions written in Java!

The problem may be a general problem for the current implementation of
BSF 2.x for the following reasons:

   1. If the defining class loader which is used to load the BSFManager
      class is a customized one, then the current implementation of
      BSFManager may not be successful in getting at the properties file
      which contains the supported BSF engines, as at the moment the
      thread's context class loader is used, which may be different from
      the customized class loader! (That's where one of  the problem has
      materialized with OOo 2.3.0 RC2.)
   2. Loading classes via "Engine.loadClass()" currently uses the
      thread's context class loader to load the classes. As OpenOffice
      does not set the context class loader explicitly there are cases,
      where some classes cannot be loaded via "Engine.loadClass()",
      which would use by default the passed-in BSFManager instance
      (which might have been loaded with a yet different class loader!).

To recollect the different possibilities a brief overview of class
loaders (CL):

    * "Bootstrap" class loader (BCL): part of the JVM, a class being
      loaded by it would return "null" as its own class loader.
    * "Extension class loader" (ECL; "extension" now called "option"
      starting with Java 6): responsible for loading those classes that
      can be found in the java extension directories (cf. System
      property "java.ext.dirs"), supplied by the Java runtime
    * "System class loader", dubbed "Application class loader" (ACL):
      responsible for loading the classes that can be found in the Java
      classpath (cf. System property "java.class.path"), supplied by the
      Java runtime.
    * "Custom class loader" (CCL), usually a subclass of URLClassLoader
      or one of its subclasses; there can be any number of CCLs in the
      system. CCLs are supposed to delegate the class loading to their
      parent, if any, before attempting to load a class by themselves,
      but they are free to not do so!
    * "Context class loader" (CTXCL): each thread may have a so called
      "context class loader", which one is supposed to honor (and e.g.
      use for class loading); a programmer may freely get and set the
      thread's context class loader (e.g.
      "Thread.getCurrentThread().{get|set}ContextClassLoader()").
    * "Defining class loader" (DCL): the class loader used to load a
      specific class (is stored with the class object).

The class loaders create a hierarchy, typically BCL, ECL, ACL, and CCL
are organized as:

    * BCL (bootstrap)
    * ECL (extensions)
    * ACL (system/application)
          o CCL1
          o CCL2
                + CCL21
                + etc.
          o etc.

As each CL may have a different environment set up, it may not be clear
at runtime, which CL is able to load which classes.

Originally, BSF used the BSFManager's DCL to load classes. In addition
it allowed to set the class loader to use for loading classes. As the
DCL may have been different to the CTXCL about two years ago I added the
usage of CTXCL with the exception of "EngineUtils.loadClass()" which
only would use the CTXCL, if the BSFManager stored class loader was null
(which for all practical purposes never would be the case).

Now, being confronted with the new OOo possible deployments, and the
manyfold possibilities of CLs being used (ECL, ACL, CCLs) it may become
a challenge to apply a strategy of deploying the possible CLs at runtime
in a way which still keeps the system quick, and makes sure that all
meaningful CL are excercised to load classes for the purpose of BSF.
(Again, CCLs could adhere to the Java suggested convention of first
using their parent to load classes - which would be great; however, we
could not rely that CCLs truly implement that delegation, as they are
not forced to.)

Thinking and experimenting with different kind of possibilities and
solutions, and trying to keep the implementation as simple as possible,
I would like to propose the following approaches to the aforementioned
two principle problems:

   1. ad loading rexources (i.e. BSF's property file that defines the
      BSF engines available):
          * first use the CTXCL and if no properties can be retrieved
            via it,
          * then use BSFManager's DCL
   2. ad class loading in "EngineUtils.loadClass8)":
         1. first use the CTXCL and if the class cannot be loaded,
         2. then use the CL that is stored with BSFManager (using
            "mgr.getClassLoader()" [as originally implemented]) and if
            the class cannot be loaded,
         3. then use the DL of BSFManager, if that is different from CL
            returned by "mg.getClassLoader()" and if the class cannot be
            loaded,
         4. then use the BSF-CL, which tries to load the class from the
            BSF temporary directory [as originally implemented].

So the rule would be simple:

    * first always use the CTXCL (which usually is the ACL), and only if
      a resource/class is not found extend the search,
    * next use the BSFManager's DCL ("EngineUtils.loadClass()" would
      honor the CL stored with the BSFManager instance and retrievable
      via its "getClassLoader()" first; but in most cases it can be
      expected that that CL would be BSFManager's DCL).

---

Now, all my tests so far (also in different use cases) indicate that
issues like the one encountered with the new OOo 2.3.0 would be solved
by these changes. In most cases resolving via CTXCL will succeed (as it
did in the past).

However, before checking the changes in (after a few more tests in
different use cases), I would like to get feedback from this list, such
that we can discuss this further.

Regards,

---rony

P.S.: Please note, not getting any feedback on this will be interpreted
by me that you concur with this assessment and changes to BSF 2.x!
:)


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message