Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Equinox » How To Avoid Classloader Activating all Bundles?
How To Avoid Classloader Activating all Bundles? [message #111168] Fri, 30 May 2008 18:02 Go to next message
Mark Melvin is currently offline Mark Melvin
Messages: 118
Registered: July 2009
Senior Member
Hi There,

I have been using a custom classloader for quite some time with a Jython=
=

plug-in I wrote for scripting purposes. This is needed (as far as I can=
=

tell) for Jython to find and load classes from OSGi bundles. However, =

when debugging an issue today I noticed that my classloader seemed to be=
=

causing *all* bundles on its search path (I don't search *all* bundles -=
I =

have an ignore list) to be started. Naturally this is really bad...

Debugging this issue a bit, I found this hunk of code in BundleHost.java=
:

try {
return (loader.loadClass(name));
} catch (ClassNotFoundException e) {
// this is to support backward compatibility in eclipse
// we always attempted to start a bundle even if the class was not fo=
und
if (!(e instanceof StatusException) && (bundledata.getStatus() & =

Constants.BUNDLE_LAZY_START) !=3D 0 && =

!testStateChanging(Thread.currentThread()))
try {
// only start the bundle if this is a simple CNFE
framework.secureAction.start(this, START_TRANSIENT);
} catch (BundleException be) {
framework.adaptor.getFrameworkLog().log(new =

FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, =

FrameworkLogEntry.WARNING, 0, be.getMessage(), 0, be, null));
}
throw e;
}

So, it appears that if a class is not found the bundle is always started=
! =

Is this not defeating the whole purpose of the lazy activation mechanism=
? =

I realize I am the one that cause the CNFE, but I really don't know of a=
ny =

other way to accomplish what I need to do. I guess I could not query th=
e =

bundle if it is not active, but then I won't be able to resolve anything=
=

from bundles that have not yet been activated/started by the workbench.=
=

This is a drag too.

So I guess my question is, is there a way to write a classloader that =

looks for a class in all bundles *without causing all bundles to be =

started*? Basically what I am doing now is this:

Bundle[] loaders =3D getPluginBundles();
if (loaders !=3D null) {
for (int i =3D 0; (i < loaders.length) && (result =3D=3D nu=
ll); i++) =

{
try {
result =3D loaders[i].loadClass(name);
break;
} catch (ClassNotFoundException e) {
// Ignore exception now. If necessary we'll throw
// a ClassNotFoundException caller.
}
}
}
return result;

(The method getPluginBundles() calls =

<mybundle>.getBundleContext().getBundles(), runs them through my ignore =
=

list, and caches the result.)

Thanks,
Mark.
Re: How To Avoid Classloader Activating all Bundles? [message #111189 is a reply to message #111168] Fri, 30 May 2008 18:20 Go to previous messageGo to next message
Mark Melvin is currently offline Mark Melvin
Messages: 118
Registered: July 2009
Senior Member
I just noticed that checking if the bundle is active before trying to lo=
ad =

from it isn't as bad as I thought as <<LAZY>> bundles seem to be ACTIVE=
, =

but I do get a class loading failure for bundles in the RESOLVED state. =
=

Is there anything else I can do here?

(Oh, and I fixed the bug in my originally-posted code... ;-)

Mark.


On Fri, 30 May 2008 18:02:13 -0400, Mark Melvin <mark.melvin@onsemi.com>=
=

wrote:

> Hi There,
>
> I have been using a custom classloader for quite some time with a Jyth=
on =

> plug-in I wrote for scripting purposes. This is needed (as far as I c=
an =

> tell) for Jython to find and load classes from OSGi bundles. However,=
=

> when debugging an issue today I noticed that my classloader seemed to =
be =

> causing *all* bundles on its search path (I don't search *all* bundles=
- =

> I have an ignore list) to be started. Naturally this is really bad...=

>
> Debugging this issue a bit, I found this hunk of code in BundleHost.ja=
va:
>
> try {
> return (loader.loadClass(name));
> } catch (ClassNotFoundException e) {
> // this is to support backward compatibility in eclipse
> // we always attempted to start a bundle even if the class was not =
=

> found
> if (!(e instanceof StatusException) && (bundledata.getStatus() & =

> Constants.BUNDLE_LAZY_START) !=3D 0 && =

> !testStateChanging(Thread.currentThread()))
> try {
> // only start the bundle if this is a simple CNFE
> framework.secureAction.start(this, START_TRANSIENT);
> } catch (BundleException be) {
> framework.adaptor.getFrameworkLog().log(new =

> FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, =

> FrameworkLogEntry.WARNING, 0, be.getMessage(), 0, be, null));
> }
> throw e;
> }
>
> So, it appears that if a class is not found the bundle is always =

> started! Is this not defeating the whole purpose of the lazy activati=
on =

> mechanism? I realize I am the one that cause the CNFE, but I really =

> don't know of any other way to accomplish what I need to do. I guess =
I =

> could not query the bundle if it is not active, but then I won't be ab=
le =

> to resolve anything from bundles that have not yet been =

> activated/started by the workbench. This is a drag too.
>
> So I guess my question is, is there a way to write a classloader that =
=

> looks for a class in all bundles *without causing all bundles to be =

> started*? Basically what I am doing now is this:
>
> Bundle[] loaders =3D getPluginBundles();
> if (loaders !=3D null) {
> for (int i =3D 0; (i < loaders.length) && (result =3D=3D =
null); =

> i++) {
> try {
> result =3D loaders[i].loadClass(name);
> break;
> } catch (ClassNotFoundException e) {
> // Ignore exception now. If necessary we'll throw=

> // a ClassNotFoundException caller.
> }
> }
> }
> return result;
>
> (The method getPluginBundles() calls =

> <mybundle>.getBundleContext().getBundles(), runs them through my ignor=
e =

> list, and caches the result.)
>
> Thanks,
> Mark.
Re: How To Avoid Classloader Activating all Bundles? [message #111326 is a reply to message #111189] Mon, 02 June 2008 11:43 Go to previous messageGo to next message
Mark Melvin is currently offline Mark Melvin
Messages: 118
Registered: July 2009
Senior Member
Actually, after having looked at this for awhile I think I can be much =

smarter about caching which bundles contribute which packages, and filte=
r =

my classloading attempts that way. It should avoid the activations and =
=

speed things up considerably.

Mark.

On Fri, 30 May 2008 18:20:33 -0400, Mark Melvin <mark.melvin@onsemi.com>=
=

wrote:

> I just noticed that checking if the bundle is active before trying to =
=

> load from it isn't as bad as I thought as <<LAZY>> bundles seem to be=
=

> ACTIVE, but I do get a class loading failure for bundles in the RESOLV=
ED =

> state. Is there anything else I can do here?
>
> (Oh, and I fixed the bug in my originally-posted code... ;-)
>
> Mark.
>
>
> On Fri, 30 May 2008 18:02:13 -0400, Mark Melvin <mark.melvin@onsemi.co=
m> =

> wrote:
>
>> Hi There,
>>
>> I have been using a custom classloader for quite some time with a =

>> Jython plug-in I wrote for scripting purposes. This is needed (as fa=
r =

>> as I can tell) for Jython to find and load classes from OSGi bundles.=
=

>> However, when debugging an issue today I noticed that my classloader =
=

>> seemed to be causing *all* bundles on its search path (I don't search=
=

>> *all* bundles - I have an ignore list) to be started. Naturally this=
=

>> is really bad...
>>
>> Debugging this issue a bit, I found this hunk of code in =

>> BundleHost.java:
>>
>> try {
>> return (loader.loadClass(name));
>> } catch (ClassNotFoundException e) {
>> // this is to support backward compatibility in eclipse
>> // we always attempted to start a bundle even if the class was not=
=

>> found
>> if (!(e instanceof StatusException) && (bundledata.getStatus() & =

>> Constants.BUNDLE_LAZY_START) !=3D 0 && =

>> !testStateChanging(Thread.currentThread()))
>> try {
>> // only start the bundle if this is a simple CNFE
>> framework.secureAction.start(this, START_TRANSIENT);
>> } catch (BundleException be) {
>> framework.adaptor.getFrameworkLog().log(new =

>> FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, =

>> FrameworkLogEntry.WARNING, 0, be.getMessage(), 0, be, null));
>> }
>> throw e;
>> }
>>
>> So, it appears that if a class is not found the bundle is always =

>> started! Is this not defeating the whole purpose of the lazy =

>> activation mechanism? I realize I am the one that cause the CNFE, bu=
t =

>> I really don't know of any other way to accomplish what I need to do.=
=

>> I guess I could not query the bundle if it is not active, but then I =
=

>> won't be able to resolve anything from bundles that have not yet bee=
n =

>> activated/started by the workbench. This is a drag too.
>>
>> So I guess my question is, is there a way to write a classloader that=
=

>> looks for a class in all bundles *without causing all bundles to be =

>> started*? Basically what I am doing now is this:
>>
>> Bundle[] loaders =3D getPluginBundles();
>> if (loaders !=3D null) {
>> for (int i =3D 0; (i < loaders.length) && (result =3D=3D=
null); =

>> i++) {
>> try {
>> result =3D loaders[i].loadClass(name);
>> break;
>> } catch (ClassNotFoundException e) {
>> // Ignore exception now. If necessary we'll thro=
w
>> // a ClassNotFoundException caller.
>> }
>> }
>> }
>> return result;
>>
>> (The method getPluginBundles() calls =

>> <mybundle>.getBundleContext().getBundles(), runs them through my igno=
re =

>> list, and caches the result.)
>>
>> Thanks,
>> Mark.
>
Re: How To Avoid Classloader Activating all Bundles? [message #111421 is a reply to message #111168] Tue, 03 June 2008 06:01 Go to previous messageGo to next message
Eclipse User
Originally posted by: erdal.karaca.airbus.com

I encountered similar problems.
In my case, I created executable extensions using IConfigurationElement.
All plugins contributing to this extension point were loaded at startup.

The solution to this was a "LazyLoader" which created dynamic proxies.
The plugins were then loaded on demand ;-)

If you think, this can help you either, have a look the following
bug/enhancement report on bugzilla:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=232271
Re: How To Avoid Classloader Activating all Bundles? [message #111438 is a reply to message #111421] Tue, 03 June 2008 10:34 Go to previous messageGo to next message
Mark Melvin is currently offline Mark Melvin
Messages: 118
Registered: July 2009
Senior Member
Hi Erdal,

Thanks for the reply, but I am a little confused as to the particular =

problem you were experiencing. You are in control of when you create =

objects with createExecutableExtension so can you not just create simple=
=

proxy objects with a reference to the IConfigurationElement of interest =
=

when you read the extension registry, and only call =

createExecutableExtension when necessary (i.e. on demand and "lazy")? O=
r =

were you trying to come up with a more general-purpose solution to this?=


Mark.

On Tue, 03 Jun 2008 06:01:16 -0400, Erdal Karaca <erdal.karaca@airbus.co=
m> =

wrote:

> I encountered similar problems.
> In my case, I created executable extensions using IConfigurationElemen=
t. =

> All plugins contributing to this extension point were loaded at startu=
p.
>
> The solution to this was a "LazyLoader" which created dynamic proxies.=

> The plugins were then loaded on demand ;-)
>
> If you think, this can help you either, have a look the following =

> bug/enhancement report on bugzilla:
>
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=3D232271
>
>
>
Re: How To Avoid Classloader Activating all Bundles? [message #111460 is a reply to message #111438] Tue, 03 June 2008 15:02 Go to previous messageGo to next message
Eclipse User
Originally posted by: erdal.karaca.airbus.com

Did you visit the link provided? - You may find the general purpose
solution ;-)

https://bugs.eclipse.org/bugs/show_bug.cgi?id=232271


Mark Melvin wrote:

> Hi Erdal,

> Thanks for the reply, but I am a little confused as to the particular
> problem you were experiencing. You are in control of when you create
> objects with createExecutableExtension so can you not just create simple
> proxy objects with a reference to the IConfigurationElement of interest
> when you read the extension registry, and only call
> createExecutableExtension when necessary (i.e. on demand and "lazy")? Or
> were you trying to come up with a more general-purpose solution to this?

> Mark.
Re: How To Avoid Classloader Activating all Bundles? [message #111485 is a reply to message #111460] Tue, 03 June 2008 16:03 Go to previous message
Mark Melvin is currently offline Mark Melvin
Messages: 118
Registered: July 2009
Senior Member
I did visit the link provided but I wasn't exactly sure what you were =

trying to do. It looks to me like yes, you are providing a general =

purpose proxy class that instantiates the real class the first time it i=
s =

accessed (via a declared interface). It is kind of cool and magical (bu=
t =

not so straightforward...). ;)

M.

On Tue, 03 Jun 2008 15:02:56 -0400, Erdal Karaca <erdal.karaca@airbus.co=
m> =

wrote:

> Did you visit the link provided? - You may find the general purpose =

> solution ;-)
>
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=3D232271
>
>
> Mark Melvin wrote:
>
>> Hi Erdal,
>
>> Thanks for the reply, but I am a little confused as to the particular=
=

>> problem you were experiencing. You are in control of when you create=
=

>> objects with createExecutableExtension so can you not just create =

>> simple proxy objects with a reference to the IConfigurationElement o=
f =

>> interest when you read the extension registry, and only call =

>> createExecutableExtension when necessary (i.e. on demand and "lazy")?=
=

>> Or were you trying to come up with a more general-purpose solution t=
o =

>> this?
>
>> Mark.
>
>
Previous Topic:jBPM or other workflow engine
Next Topic:Is org.eclipse.update.configurator required for server-side apps?
Goto Forum:
  


Current Time: Sun Apr 20 03:05:43 EDT 2014

Powered by FUDForum. Page generated in 0.02239 seconds