Hi there,

I'm resurrecting an old thread that went relatively unnoticed (only one
reply) but that has been bothering me when I thought back about it lately.

The problem is described in the original message below, but in one word:
I'm looking for best practices when it comes to cleaning after a service
is unregistered: what should we do with the objects that were
created/provided by this service.

There doesn't seem to be a general answer. I can imagine a factory
service that creates objects, that I want to disable (probably
temporarily) but leave my objects intact. On the other hand, I can also
imagine objects that are tied to the lifecycle of the service that
provided them (and must be released at the same time the service is
unregistered). There are probably also some "short lived" objects that
can continue being active after their service is gone, but only for a
bounded duration (e.g, to finish a transaction).

There may be different reasons a service is unregistered and the reason
is unknown to the consumer. The reason that gets me wondering is when
an implementation bundle is uninstalled in order to install a newer
version. In that case, you really want those objects provided by the old
service instance to be cleaned up as well, or else a reference on them
will prevent the old bundle's classloader to be garbage collected, and
they may also lead to an inconsistent state if old and new object
instances of the same class coexist. Other times, services come and go
for "business" reasons that have nothing to do with the bundle's
lifecycle. (a crazy solution to distinguish the two would be be using a
BundleTracker to clean up objects when their "owning" bundle is
uninstalled).

My question here is: how do you deal with this? What are the best
practices you learned along the way? I couldn't find much literature on
that topic and I don't


So far, I came up with this: It would be nice if we had a way to know
that objects returned by service A's method foo must be cleaned when
it's gone, but not objects returned by method bar... Or that service A
expects us to store objects returned by method baz in a WeakReference.
That's probably too many details. A more reasonable approach would be
for the service to have a "retention policy" for all of the objects
created by its methods. For instance, the property objects.retention
could be Lifecycle (to mean "null references on objects are provided
when the service is unregistered"), Weak ("only store them in a
weakreference) or Bundle (which would be the default, and mean do
whatever you want but you'd better clean them when the bundle that
"owns" them is uninstalled).

Service frameworks could then provide some support, for instance
frameworks that use service proxies (like iPOJO, Blueprint or Peaberry)
could make those generated proxies return proxified versions the created
objects as well, which would appropriately follow those instructions.
Ok, I'm worried about the runtime overhead, but I think consuming
dynamic services without caring too much is worth it, and it should be
configurable. (I didn't think the possible properties through and
through, those are examples).

Of course, none of this happens with DS' static references, but they
don't solve everything either.

So, am I wrong to worry about this, did I forget anything, am I mistaken
somewhere or am I missing an existing solution? Please enlighten me :).

Thanks,

-- 
Simon




Holger Hoffstätte wrote on 19/11/2010 10:41:
> On 18.11.2010 14:45, Alexander Shutyaev wrote:
>> I have a question about what happens to class instances when bundle
>> containing the class unloads. Let's say I have:

>
> Pretty much nothing: just because a bundle was unloaded does not mean
> that the class will be force-wiped from memory. A class (and its
> classloader) will only be GC'ed when all its instances can be/have been
> GC'ed. AFAIR the framework will also not pull down/reestablish the
> wiring between packages/bundles unless it is refreshed.
>
> -h

>> 1. bundle "org.foo.animal" containing interface Animal
>> 
>> public interface Animal
>> {
>>      String getName();
>>      int getType();
>> }
>> 
>> 2. bundle "org.foo.animal.cat <http://org.foo.animal.cat>" containing
>> class Cat
>> 
>> public class Cat implements Animal;
>> 
>> 3. bundle "org.foo.supplier" containing interface AnimalSupplier
>> 
>> public interface AnimalSupplier
>> {
>>      Animal getAnimal();
>> }
>> 
>> 4. and finally "org.foo.supplier.cat <http://org.foo.supplier.cat>"
>> containing class CatSupplier
>> 
>> public class CatSupplier implements AnimalSupplier
>> {
>>      public Animal getAnimal()
>>      {
>>           return new Cat();
>>      }
>> }
>> 
>> import/export dependencies are ok, and there is only one service -
>> CatSupplier published under AnimalSupplier
>> 
>> Some other bundle invokes getAnimal() on CatSupplier through
>> AnimalSupplier service and so obtains an instance of Cat under Animal
>> interface. This our bundle depends only on org.foo.animal and
>> org.foo.supplier and knows nothing about cats =) Next thing I unload cat
>> bundles. This causes my bundle to loose AnimalSupplier reference and
>> that's ok. But what about my instance of Cat class? I still have it as
>> an object but the class itself is not there (because the bundle
>> containing it was unloaded). What happens if I try to invoke methods on
>> my Cat object through Animal interface?
>> 
> 
> 
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev

_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to