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 >