Raymond,

Thank you for your reply (and the diagram).

The biggest advantage of migrating to an OSGi classloader scheme would be
that apart from module isolation, OSGi would also provide module versioning,
enabling multiple versions of SCA runtime to exist within a single VM. OSGi
would also enable Tuscany modules to be dynamically installed, started and
uninstalled. The use of multi-parent classloaders to load modules in Tuscany
would require the same amount of code changes as migrating to OSGi, but it
would be much harder to implement versioning and dynamic replacement of
modules (which come for free with OSGi).

The desired visibility of classes that you have listed correspond to the
static dependencies that currently exist in the code. The actual visibility
that exists today includes arrows from the core modules to extensions,
forming a cycle. It is this visibility that is used to locate and start
modules dynamically in Tuscany today. There is also an arrow from the Axis
library to binding.ws.axis2, through the thread context classloader, and
even though not particularly desirable, it is not avoidable.


Thank you...

Regards,

Rajini


On 10/15/07, Raymond Feng <[EMAIL PROTECTED]> wrote:
>
> Hi, Rajini.
>
> Thank you for the detailed writeup. I copied your note into the following
> wiki page so we can capture the design points.
>
>
> http://cwiki.apache.org/confluence/display/TUSCANYWIKI/Classloading+in+Tuscany+SCA+Java
>
> I found it a bit difficult to reply in long e-mails so I decide to attack
> the problem from a slightly different angle.
>
> A) What's the purpose of classloading scheme?
> I think it's used to provide sharing and isolation of java classes.
>
> B) What are the players?
>
> 1. SCA/Tuscany APIs (and potentially other APIs such as SDO)
> 2. Tuscany runtime code
> 3. Tuscany extension code
> 4. 3rd party code that Tuscany runtime/extension depends on
> 5. Application code from SCA contributions
>
> 3) What's desired visibility?
>
> 5 --> imported java classes by the owning contribution
>   --> 1
>
> 2 --> 1
>   --> 4
>
> 3 --> 2 (SPI portion)
>   --> 1
>   --> 4
>   --> potentially other extensions
>
> I created a graph at
>
> http://cwiki.apache.org/confluence/download/attachments/68801/classloader-dependencies.png
> as the starting point. Once we have the relationship flushed out, we could
> then apply techniques such as OSGi or multi-parent classloaders, or a
> combination to enforce the loading scheme.
>
> Raymond
>
> ----- Original Message -----
> From: "Rajini Sivaram" <[EMAIL PROTECTED]>
> To: <tuscany-dev@ws.apache.org>
> Sent: Monday, October 15, 2007 12:52 AM
> Subject: Re: Classloading in Tuscany
>
>
> > Mike,
> >
> > There are two sets of classloading in Tuscany that we need to look at
> and
> > these can be handled independently of each other.
> >  1) Classloading architecture for SCA contributions
> >  2) Classloading architecture for SCA runtime modules
> >
> > In both cases, there are two ways of improving modularity in Tuscany
> >  a) Use separate classloaders per module to provide isolation, using a
> > classloader architecture similar to OSGi, but without actually running
> in
> > an
> > OSGi runtime.
> >  b) Use OSGi bundles to provide module isolation and versioning, where
> the
> > versioning support would rely on an OSGi runtime.
> >
> >
> > For both 1) and 2), we could support a) and/or b).
> >
> > Tuscany already supports 1b), and the proposed fixes will support 1a).
> >
> > Tuscany does not implement 2a) or 2b), and if done properly, the
> > implementation would required code changes that are pervasive across
> > Tuscany. So the question is - do we really want to run Tuscany modules
> as
> > separate OSGi bundles (or isolate modules using separate classloaders)?
> > IMHO, it is only worth the hassle, if Tuscany modules are properly
> > versioned
> > and dynamically replaceable - ie, run as bundles in an OSGi runtime
> (2b).
> > The proposed fixes do not implement 2a) and provide a partial solution
> for
> > 2b) based on OSGi manifest files to minimize code changes to Tuscany.
> >
> >
> > 1) Classloading architecture for SCA contributions
> >
> > At the moment, OSGi bundle contributions can be used in Tuscany which
> > provide modularity and versioning with the help of an OSGi runtime.
> Plain
> > Jar contributions or folders use a single classloader at the moment and
> > the
> > proposed fixes will introduce contribution classloaders to isolate
> > contributions.
> >
> > SCA contributions can specify dependencies in terms of import/export
> > statements in the same way as OSGi bundles. If you consider Java
> > contributions, SCA contribution dependencies are a subset of OSGi bundle
> > dependencies, because SCA does not support versioning or any of the
> other
> > attributes that can be associated with importing packages in OSGi. So
> SCA
> > contribution classloading will be a simpler version of OSGi bundle
> > classloading. The code for supporting SCA import/export is already in
> > place
> > in Tuscany- it just doesn't get used because the thread context
> > classloader
> > is currently used to resolve classes.
> >
> > 2) Classloading architecture for SCA runtime modules
> >
> > At the moment, Tuscany uses a single classloader for the runtime and its
> > dependencies, and even though Tuscany runtime architecture uses
> extensible
> > modules with reasonably well defined dependencies, module isolation is
> not
> > achieved because of the use of a single classloader. Tuscany also has
> > dependencies on many libraries which rely on the thread context
> > classloader.
> >
> >
> > Even though we are looking at running Tuscany in an OSGi runtime to
> > support
> > distributed-OSGi, at the moment we are still assuming that by default
> > Tuscany would be run without an OSGi runtime. Hence the proposed fixes
> aim
> > to minimize Tuscany changes required to implement 2b). Tuscany's use of
> > thread context classloader will be removed wherever possible, but the
> > requirement on thread context classloader will not be removed altogether
> > since it is used by libraries that Tuscany depends on.
> >
> >
> > There are two issues with modularizing Tuscany runtime using OSGi or
> > OSGi-style classloading. Thread context classloaders and OSGi dont go
> very
> > well together. And the extension module architecture used by Tuscany
> where
> > a
> > core module is extended through the use of extension modules ends up in
> a
> > classloader hierarchy which is the reverse of what is required - the
> core
> > bundle does not have visibility of the classes from the extension
> bundles.
> >
> > There is an OSGi RFP which addresses classloading enhancements for OSGi
> > including those required for applications relying on thread context
> > classloaders. Possible solutions to implement 2b) now include the use of
> > DynamicImport-Package, Eclipse buddy policy, Spring-OSGi Extender Model
> or
> > OSGi services.
> >
> > If we want to implement 2a) and 2b) properly at some point, it might
> make
> > sense to provide a solution that uses a utility library to implement all
> > classloading (which can then do something different based on whether
> > Tuscany
> > is running inside an OSGi runtime or outside). But the changes required
> > for
> > this will be pervasive across Tuscany code.
> >
> >
> > Thank you...
> >
> > Regards,
> >
> > Rajini
> >
> > On 10/12/07, Mike Edwards <[EMAIL PROTECTED]> wrote:
> >>
> >> Rajini,
> >>
> >> Little though here:
> >>
> >> - can this be done in a way that moves us closer to the OSGi handling
> of
> >> classloading?
> >>
> >> - so if ever we wanted an OSGi style runtime, it would be easier to
> >> adapt what we have...
> >>
> >>
> >> Yours,  Mike.
> >>
> >> Rajini Sivaram wrote:
> >> > 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
> >> >>
> >> >
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: [EMAIL PROTECTED]
> >> For additional commands, e-mail: [EMAIL PROTECTED]
> >>
> >>
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>

Reply via email to