It depends.

It depends upon the contract of the service. What is the lifetime of any 
object provided by the service? Sometimes the object will have infinite 
life. E.g. a String, Integer or other basic type. Sometimes the life of 
the object is coupled to the classloader of the objects type. E.g. an 
immutable Event object. Sometimes the life of the object is coupled to 
that of the service. E.g. an Configuration object.

Given that there is no way to take an object away from someone who has a 
reference to the object, the service contract should state the behavior of 
the object outside of its defined life time. E.g. what happens when I call 
methods on a Configuration object after the ConfigAdmin service has been 
unregistered? Examples of possible behavior are do nothing, throw 
exception, keep working. Care must be put into the API design to make the 
best choices. For some methods, keep working is a valid choice. If the 
method just returns some immutable value, it may always be safe to return 
it. E.g. a String identifier. For other methods, it may make sense to 
throw an exception, e.g. IllegalStateException, so the caller fails fast.

There is no one best practice here.
-- 

BJ Hargrave
Senior Technical Staff Member, IBM
OSGi Fellow and CTO of the OSGi Alliance
[email protected]

office: +1 386 848 1781
mobile: +1 386 848 3788





From:   Simon Chemouil <[email protected]>
To:     OSGi Developer Mail List <[email protected]>
Date:   2011/02/18 16:12
Subject:        Service cleanup best practices (Was: [osgi-dev] What 
happens to class        instances when bundle containing        the class 
unloads)
Sent by:        [email protected]



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
> [email protected]
> https://mail.osgi.org/mailman/listinfo/osgi-dev

_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev

_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to