On 10/11/07, Rajini Sivaram <[EMAIL PROTECTED]> wrote:
>
> Hello,
>
> Tuscany's use of classloaders doesn't seem to be well-defined, even though
> the concept of a runtime classLoader and contribution classloaders should
> have made it easy to isolate these namespaces. All Tuscany samples and
> tests
> are currently run with a single application classloader containing
> absolutely everything including Tuscany, all the jar files Tuscany
> requires
> and all the Java contribution jars/folders.
>
> I am running Tuscany as a bundle inside an OSGi runtime, and came across
> some issues with classloading when multiple classloaders are used.
> Even though these can be fixed for OSGi without changes to the non-OSGi
> related code in Tuscany, it will be good to fix these properly in Tuscany
> since these issues affect anyone who wants to use Tuscany without a great
> big classloader hierarchy containing Tuscany, all its dependencies and all
> contributions.
> Here is my understanding of classloaders used by Tuscany:
>
> 1) Tuscany Runtime classloader
> This is the classloader used to load Tuscany itself. It should be able to
> locate all Tuscany jar files and all its dependent jar files (eg. axis2).
> There are many locations in Tuscany which explicitly read the
> classloader used to load one Tuscany class in order to load another
> Tuscany
> class. For example, many of the files defined in META-INF/services  and
> the
> classes they refer to are loaded in this way.
>
> 2) Contribution classloaders
> Referred to as application classloader in the DefaultSCADomain, a separate
> classloader can (in theory) be used to refer to the contributions - in the
> case of DefaultSCADomain, this is a single classloader associated with a
> single contribution.
>
> There is currently no concept of a contribution classloader for each
> contribution (except for OSGi contributions), and all resolution of
> classes
> from contributions is done using a single classloader. This does not
> reflect
> the SCA specification, which requires contribution imports/exports to be
> explicitly specified - requiring multiple classloaders to enforce the
> import/export definition during class resolution.
>
> 3) Thread context classloader
> Tuscany sets thread context classloader only in one class -
> HotUpdatableSCADomain (which sets Context classloader to a single
> URLClassLoader containing all the contribution jar files, with the
> original
> context classloader as parent).
>
> Tuscany uses the thread context classloader in around 30 different
> locations. Around half of these have FIXMEs saying that the classloader
> should be passed in. Many of these uses of the context classloader are
> trying to obtain the runtime classloader. And at least one is trying to
> obtain the contribution classloader.
>
> Many libraries which are used by Tuscany require the thread context
> classloader to be able to load the library classes. Most of these use the
> factory pattern and dynamically load implementation classes to create
> instances using the context classloader (eg.
> javax.xml.datatype.DataTypeFactory.newInstance()). The context classloader
> should in these cases to be able to find classes in Tuscany's dependent
> jar
> files, and hence the classloader used to load these dependent jars should
> be
> on the thread context classloader hierarchy.
>
> Axis2 libraries (and possibly others) use the thread context classloader
> to
> load Tuscany classes. Axis2 needs to find Tuscany's message receivers
>
> org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInOutSyncMessageReceiverand
> org.apache.tuscany.sca.binding.ws.axis2.Axis2ServiceInMessageReceiver, and
> these are loaded by Axis2 using the  context classloader. So Tuscany
> runtimeClassloader should be on the thread context classloader hierarchy.
>
> 4) Java Application classloader
> Tuscany doesn't directly rely on the application classloader (the
> classloader corresponding to CLASSPATH). But since Tuscany doesn't set the
> thread context classloader, for any application that doesn't explicitly
> set
> thread context classloader, there is an indirect dependency on the
> application classloader, and hence CLASSPATH should contain everything
> required by the thread context classloader (which at the moment includes
> the
> entire world).
>
> So we have the following requirements on classloaders:
>
>
>    1. Tuscany runtime classloader should find Tuscany and all its
>    dependencies (essentially tuscany-sca-manifest.jar).
>    2. Contributions are not required to be on the classpath, nor do they
>    have to be visible to the thread context classloader. One classloader
> per
>    contribution is required to enforce SCA contribution import/export
>    semantics.
>    3. Thread context classloader should be able to see Tuscany's
>    dependencies and also Tuscany classes - so this can be the same as (or
> a
>    child of) the Tuscany runtime classloader.
>    4. Any code using Tuscany should either have Tuscany runtime and its
>    dependencies on the CLASSPATH, or should set the thread context
> classloader
>    for its threads using Tuscany. All Tuscany tests rely on CLASSPATH,
> while
>    Tuscany can be run inside OSGi without CLASSPATH, by setting the
> context
>    classloader.
>
>
> I would like to propose the following fixes to Tuscany classloading (my
> aim
> is to implement neater isolation without too much impact on the code):
>
> 1) Fix contribution classloading to enforce SCA contribution specification
> by using one classloader per contribution. Remove the requirement for
> contributions to be present in the classpath - Tuscany runtime
> classloader,
> thread context classloader and the application classloader should not be
> required to see the contribution classes.
>
> 2) Remove unnecessary usages of thread context classloader in Tuscany
> where
> the classloader that is required is the  Tuscany Runtime classloader. It
> should be possible in many cases to determine the classloader directly
> without having to pass classloaders around. This is already done in some
> places, so this is just making the code consistent.
>
> 3) There are many uses of the thread context classloader where it is not
> very clear which classloader is actually required. I would suggest that as
> far as possible, Tuscany should avoid using the thread context
> classloader,
> and in places where it cannot be avoided without major changes, the code
> should be commented to show which classloader is required.
> As an example (the FIXME is from the existing code)
>
> *public JAXBElement<?> create(ElementInfo element, TransformationContext
> context) {*
> *    .....*
> *    ClassLoader classLoader = context != null ? context.getClassLoader()
> :
> null;*
> *    if (classLoader == null) {*
> *        //FIXME Understand why we need this, the classloader should be
> passed in*
> *        classLoader = Thread.currentThread().getContextClassLoader();*
> *    }*
> *    Class<?> factoryClass = Class.forName(factoryClassName, true,
> classLoader);*
> *    ....*
> *}*
>
> Given that Tuscany and its dependencies need to be visible from the thread
> context classloader anyway because other libraries need them there, this
> change is to merely to clean up Tuscany classloading and provide more
> clarity. It does not aim to remove the external dependencies on the thread
> context classloader.
>
> 4) It will be good to ensure that all uses of the Tuscany runtime
> classloader (eg. to load META-INF/services) continue to work even if each
> Tuscany module was loaded by a different classloader (ie, Tuscany runtime
> classloader is a hierarchy of module classloaders rather than a single
> one).
> This is not strictly necessary at the moment, but it is necessary if we
> want
> to package Tuscany modules as separate OSGi bundles.
>
> 5) Document Tuscany's requirements on classloaders (CLASSPATH and thread
> context classloader).
>
>
> I would appreciate your feedback, both regarding whether there is better
> way
> to fix this, and on areas which I have missed out or
> misunderstood. I will be happy to provide a patch if this is an acceptable
> solution.
>
>
>
>
> Thank you...
>
> Regards,
>
> Rajini
>

That all sounds good to me, i've also struggled with classloaders in the
past, it is a bit hotchpotch at the moment so if you want to have a go at
cleaning things up i think that would be wonderful.

If you were to just submit one big patch that tries to fix it all in one go
that may get bogged down in discussion about approaches, so the smaller bits
you can break this down into with a few smaller discrete patches thats
better. Don't worry to much if you can't though, one big patch is fine if
thats what it takes.

   ...ant

Reply via email to