[jsr-291-eg] Use of the system classloader

BJ Hargrave hargrave at us.ibm.com
Wed Aug 30 10:06:57 EDT 2006


We have an open issue (346) in OSGi to address this subject area for JSR 
291. I am including the text of the issue below as well as a some relevant 
comments from Tom Watson.



Summary: Class loading enhancements 

Description:   
Opened: 2006-07-14 17:13 

Many libraries exist that use the context classloader or reflection to 
load
classes.  These are sometimes at odds with the OSGi classloading model's 
desire
to structure classloading.  While there are typically ways around the 
issues,
they are sometimes not obvious and they have certain drawbacks.

The general issue is that many times libraries need access to a class or
resource that is specified declaratively.  These declared 
classes/resources are
generally not part of the library itself.  Instead they usually are 
delivered
in a separate component (or bundle).  Some examples are log4j

In OSGi you can work around these issues using the following technics:

1) Require client bundles that use the library to export all packages 
which
they want the library to have access and have the library bundle do a
DynamicImport-Package: * to gain access to the packages it needs.

This has the unfortunate side-effect of forcing client bundles to expose
(export) packages that it may not want to for general consumption.  It 
also
introduces many of the common issues associated with dynamic import for 
the
library bundle: cannot load the same named package from different sources, 
have
to worry about others replacing private packages of your bundle if they 
export
the same package.

2) Require client code that use the library bundle to set the context
classloader to client code's classloader before they call the library 
classes. 
The client code then must ensure that the context classloader is set back 
to
the original context classloader after each library call.  This is very
tedious, error prone, and only works if the library uses the context
classloader to load dynamic classes.

A mechnism is needed to better support these types of scenarios.  Equinox 
has
devised a buddy classloading concept that we should consider.  See
https://bugs.eclipse.org/bugs/show_bug.cgi?id=87775 for more details on 
the
requirements and a possible solution.


------- Comment #1 From Jeff McAffer 2006-07-14 22:04 ------- 
Further to point #1, the use of import package (any flavour) introduces a
dependency between the importer and the exporter such that if the exporter 
is
refreshed, the importer gets restarted.  In the case of libraries like 
log4j
and hibernate, that dependency is invalid.  These libraries are merely 
brokers
for events or data (respectively) and do themselves depend on these other
packages.  They just need the packages at some point in time as driven by 
data
they are processing.


------- Comment #2 From BJ Hargrave 2006-08-25 15:38 ------- 
I am moving this to 4.1 since I think these class loading issues are 
critical
for JSR 291 to address.


------- Comment #3 From BJ Hargrave 2006-08-25 16:28 ------- 
Some other important class loader points raised by the spring-osgi work 
are:

1) Need for the OSGi spec to define the value of the Thread 
contextClassLoader.
Right now this is unspecified by the framework spec. Like the doPrivileged
calls made by the framework before calling the BundleActivator, 
*Listeners,
etc., the framework must also push a context classloader with access to 
the
bundle's classes before calling these methods (and restoring the previous 
value
when they return). Context class loaders are commonly used by enterprise 
code
and the spring-osgi work is planning to enable AOP proxies to be advised 
to
push the bundle's classloader as the context classloader when calling OSGi
services. We need to figure out the right thing to do here. Having the
framework simply pushing the bundle's classloader as the context class 
loader
will break some of the use cases supported by the Eclipse extensions. The 
use
cases addressed by the ContextFinder and Buddy Class Loading work from 
Eclipse
must be considered. 

2) Spring AOP uses dynamically generated proxy classes to wrap objects 
(such an
OSGi service). These proxy classes can be advised to also implement 
additional
interfaces (beyond those implemented by the wrapped object). So the 
classloader
which loads the dynamically generated proxy class needs access to the 
classes
of the bundle the wrapped object comes from as well as the bundle 
providing the
advice. Currently Spring is creating a chained classloader which chains 
the
bundle classloader and the advice's classloader together. Since the 
bundle's
classloader is not available via an API, they do something similar to
http://wiki.eclipse.org/index.php/BundleProxyClassLoader_recipe to chain 
the
classloaders. We could provide a Bundle.getClassLoader() API to make this
easier, but during R4 we discussed and made an explicit choice not to 
expose
ClassLoader in the API and rather put the relavent methods on Bundle
(loadClass, etc.) Dynamic-ImportPackage is not appropriate here since the
bundles do not know apriori that this AOP proxying will be occuring and
Dynamic-ImportPackage is too promiscuous. I see 2 possible solutions. (1) 
Add
some methods which creates a classloader which chains a set of bundle's
together. This could be on FrameworkUtil. However it still puts 
ClassLoader in
the API but the Proxy.getProxyClass method requires a ClassLoader object
anyway. Also the created classloader would have access to all the classes
reacheable from both bundles. (2) Define a method for a bundle to be wired 
to a
specific package after it has been resolved: a way to dynamically create a
static wire. This would enable a package from a specific bundle to be 
wired to
an already resolved bundle. Then that bundle would be used  as the 
classloader
for the generated proxy. This would limit the newly visible classes to the
newly wired package but a ClassLoader object is still needed for proxy 
class
reification.


------- Comment #4 From Jeff McAffer 2006-08-26 08:14 ------- 
Note that there is Aspect related work going on in the Equinox Incubator's
Aspects work area.  They have defined some interesting ways of both 
talking
about aspect contributions and impleenting the needed classloading 
structures.

=========================================================

Tom Watson also made the following relavent comments:

> The code pattern below:
> 
> ClassLoader old = Thread.currentThread().getContextClassLoader();
> try {
> 
> Thread.currentThread().setContextClassLoader(this.getClass().
> getClassLoader());
>   // Call the factory
>   ...
> } finally {
>   Thread.currentThread().setContextClassLoader(old);
> }
> 
> This pattern is no longer needed within Equinox.  The "buddy" 
> classloader takes care of this situation for you.  The "buddy" 
> classloader design has two parts:
> 
> 1) The framework sets the default context classloader for the system
> to a special classloader.  We call this the ContextFinder.  This 
> classloader is responsible for finding the calling context.  For 
> example, a bundle calls into the javax.xml.parsers.SAXParserFactory.
> newSAXParser() provided by the VM.  The code in the VM class library
> uses the context classloader to attempt to load the parser 
> implementation.  The context classloader is the framework's 
> ContextFinder.  This classloader finds the calling bundle and uses 
> that to delegate class/resource loads for the SAXParserFactory. 
> This allows a bundle to import/require another parser implementation
> and use that instead of the parser implementation provided by the VM.
> 
> 2) There is also a concept of "buddies".  This allows bundles to be 
> added as buddies to other bundles for the purpose of class/resource 
> loading.  Imagine that the javax.xml.parsers package was not 
> provided by the VM but was instead exported by a bundle.  This 
> bundle would need the ability to load classes/resources from 
> arbitrary packages from other bundles.  We have specified various 
> buddy policies that can allow a bundle to have a set of buddies to load 
from.
> 
> We have many examples of 3rd party libraries that use the buddy 
> classloading policy.  The 3rd party code is left unchanged. 
> 



BJ Hargrave
Senior Technical Staff Member, IBM
OSGi Fellow and CTO of the OSGi Alliance
hargrave at us.ibm.com
Office: +1 407 849 9117 Mobile: +1 386 848 3788



Guillaume Sauthier <guillaume.sauthier at bull.net> 
Sent by: jsr-291-eg-bounces at membercvs.osgi.org
08/17/2006 06:02 AM
Please respond to
JSR 291 Expert Group Mail List <jsr-291-eg at membercvs.osgi.org>


To
JSR 291 Expert Group Mail List <jsr-291-eg at membercvs.osgi.org>
cc

Subject
Re: [jsr-291-eg] Use of the system classloader






Andy Piper wrote:
> I am told by the OSGi experts that use of the CCL is a very fragile 
> way of doing these kind of things in OSGi,
Yep
But a lot of libraries are looking classes in the TCCL...

>  however since this issue 
> seems to come up again and again it would be good to have an official 
> recommendation as to the right solution to these kinds of problems. 
> 
I agree :)
> Using the CCL is also not going to play very nicely in environments 
> that already use this feature (e.g. J2EE).
> 
I confirm.

Guillaume
> andy
>
> At 09:39 17/08/2006, Guillaume Sauthier wrote:
> 
>> Hi Andy
>>
>> I haven't noticed any problems by using a JNDI InitialContextFactory 
>> packaged in a bundle (Using Sun VM).
>>
>> But I agree this is an important issue.
>> We're completely stuck if Java SE/EE factories (JAXP, JAX-RPC, SAAJ, 
>> ...) only look for classes inside the System ClassLoader.
>> Sometimes, the factories tries to load from the Thread Context 
>> ClassLoader too, and that helps if we set the TCCL to the bundle 
>> ClassLoader before calling the factory.
>>
>> But this solution doesn't look very good :
>> {snip}
>> // in the Activator
>> ClassLoader old = Thread.currentThread().getContextClassLoader();
>> try {
>>
>> 
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
>>  // Call the factory
>>  ...
>> } finally {
>>  Thread.currentThread().setContextClassLoader(old);
>> }
>> {/snip}
>>
>> We're highly dependent on the factory implementation.
>>
>> BTW, Is there any trick for bundlisation of libraries that are 
>> heavily using TCCL for ClassLoading ?
>> It will be great if we can avoid all of the above code...
>>
>> Regards
>> Guillaume
>>
>> Andy Piper wrote:
>> 
>>> Hello Experts,
>>>
>>> Our internal uses of OSGi have come across a number of use cases 
>>> where Java SE relies on the system classloader for loading 
>>> resources of various types. One example is JNDI factories. 
>>> Unfortunately this creates problems when trying to load these 
>>> resources from OSGi bundles. OSGi has already solved this problem 
>>> with the URL Handler Service. This service makes it possible to 
>>> register URL handlers from OSGi bundles, so that there's a way to 
>>> load them other than by putting them in the system class path.
>>>
>>> We would like this issue to be addressed uniformly across Java SE. 
>>> For JNDI this could be solved by providing our own factory 
>>> implementation, I'm not sure whether this mechanism would so 
>>> readily apply to other scenarios however.
>>>
>>> Thoughts?
>>>
>>> andy
>>> 
_______________________________________________________________________
>>> Notice:  This email message, together with any attachments, may 
contain
>>> information  of  BEA Systems,  Inc.,  its subsidiaries  and affiliated
>>> entities,  that may be confidential,  proprietary,  copyrighted and/or
>>> legally privileged, and is intended solely for the use of the 
individual
>>> or entity named in this message. If you are not the intended 
recipient,
>>> and have received this message in error, please immediately return 
this
>>> by email and then delete it.
>>> _______________________________________________
>>> jsr-291-eg mailing list
>>> jsr-291-eg at bundles.osgi.org
>>> http://bundles.osgi.org/mailman/listinfo/jsr-291-eg
>>>
>>>
>>> 
>>
>>
>> _______________________________________________
>> jsr-291-eg mailing list
>> jsr-291-eg at bundles.osgi.org
>> http://bundles.osgi.org/mailman/listinfo/jsr-291-eg
>> 
>
> _______________________________________________________________________
> Notice:  This email message, together with any attachments, may contain
> information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated
> entities,  that may be confidential,  proprietary,  copyrighted  and/or
> legally privileged, and is intended solely for the use of the individual
> or entity named in this message. If you are not the intended recipient,
> and have received this message in error, please immediately return this
> by email and then delete it.
> _______________________________________________
> jsr-291-eg mailing list
> jsr-291-eg at bundles.osgi.org
> http://bundles.osgi.org/mailman/listinfo/jsr-291-eg
>
> 

_______________________________________________
jsr-291-eg mailing list
jsr-291-eg at bundles.osgi.org
http://bundles.osgi.org/mailman/listinfo/jsr-291-eg

-------------- next part --------------
A non-text attachment was scrubbed...
Name: guillaume.sauthier.vcf
Type: application/octet-stream
Size: 570 bytes
Desc: not available
Url : http://bundles.osgi.org/pipermail/jsr-291-eg/attachments/20060830/f98dab4a/attachment.obj 


More information about the jsr-291-eg mailing list