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]

Reply via email to