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