Thank you, Ant. I will try to split the work into small pieces and submit
separate patches.


Thank you...

Regards,

Rajini
On 10/12/07, ant elder <[EMAIL PROTECTED]> wrote:
>
> 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