views:

235

answers:

6

Once an instance of an OSGi service is retrieved from the bundle context does it become invalidated when the service is stopped?

My initial tests show that the service instance can be used even after the service bundle is stopped, which contradicts my understanding of the dynamic nature of OSGi.

I suppose this boils down to what retrieving a service (via ServiceTracker) from another bundle in the OSGi container actually does, does it create a new instance or does it give you a pointer to the instance that is registered in the container?

Are there any dangers in using the service instance after the service has been stopped?

+2  A: 

You are right in that it is contradictory to the dynamic nature of OSGi. I believe that there is no guarantee that the service will be available, although different implementations of OSGi containers and services themselves may behave differently.

For example, if the service was created and registered with Spring DM, then the service retrieved is actually a Spring based proxy to the underlying implementation, and the implementation can still disappear. Thus a service reference that refers directly to an implementation may keep that object from being removed, whereas the proxy based reference will not.

Robin
+1  A: 

The OSGi specification says:

Bundles are entities that are visible in normal application programming. For example, when a bundle is stopped, all its services will be unregistered.

So you shouldn't be able to get a service from a stopped bundle. But technically it may be possible to use it, at least as long as you hold a reference to the service object (nobody can take it away from you and it will not be GC'd). But I don't think that it is save to use the service. It may depend on other bundle resources, that are not available after the bundle has stopped.

Andreas_D
+3  A: 

This is a very good question so I digged into the specification in search for a definitive answer. It turns out that there is a whole section talking about this problem - see section 5.4 Stale References starting on page 132 of OSGi Service Platform Core Specification, Release 4, Version 4.2.

To answer your question according to the specification:

The behavior of a service that becomes unregistered is undefined. Such services may continue to work properly or throw an exception at their discretion.

And to prevent potential problems:

Bundles must listen to events generated by the Framework to clean up and remove stale references.

The specification also gives some tips how to minimize the consequences of stale references.

Pavol Juhos
Thanks for the answer, unfortunately not a definitive yes or no as I'd hoped!
James Carr
A: 

Regarding your question whether it is dangerous to use a service instance after the service has been stopped. To cite from the 4.2 core spec (5.4 Stale References):

The behavior of a service that becomes unregistered is undefined. Such services may continue to work properly or throw an exception at their discretion.

I dont want to cite the whole section of the spec here, but the following sentences are a good discussion about the danger of using stale references:

A stale reference is a reference to a Java object that belongs to the class loader of a bundle that is stopped or is associated with a service object that is unregistered. Standard Java does not provide any generic means to clean up stale references, and bundle developers must analyze their code carefully to ensure that stale references are deleted.

Stale references are potentially harmful because they hinder the Java garbage collector from harvesting the classes, and possibly the instances, of stopped bundles. This may result in significantly increased memory usage and can cause updating native code libraries to fail. Bundles using services are strongly recommended to use either the Service Tracker or Declarative Services.

akr
A: 

Once an instance of an OSGi service is retrieved from the bundle context does it become invalidated when the service is stopped?

No, the reference itself does not become invalidated. As long as something within the container is holding it, it can also not be GC'ed.

However, whether or not it will be still useful, depends only on the service implementation itself, not the container.

My initial tests show that the service instance can be used even after the service bundle >is stopped, which contradicts my understanding of the dynamic nature of OSGi.

The specifications itself indicate that such references shouldn't be held, but it's up to the implementer to take care for implementing the specifications correctly; means there is no contradiction, there is only the fact that you can implement and deploy bundles which don't behave correctly according to the specifications.

I suppose this boils down to what retrieving a service (via ServiceTracker) from another bundle in the OSGi container actually does, does it create a new instance or does it give you a pointer to the instance that is registered in the container?

The container does not create new instances of services, except if there is a ServiceFactory involved (see specs). Looking up a service should always give you a pointer to the registered instance in the container.

Are there any dangers in using the service instance after the service has been stopped?

That only depends on the service implementation; however, by doing so in a bundle, you automatically create a bundle that is not conform with the specs.

In practice, many services are implemented to release resources and references and will not respond properly any longer.

Dieter
A: 

A service reference should never be kept as a reference. You should always look up a service at runtime. This ties you to the OSGI api however, whihc is not always wanted.

Have a look at - OSGI serviceTracker - OSGI declarative services - OSGI BluePrint - Spring DM - Peaberry - iPojo

which all take care of the dynamism for you, most of them with no OSGI api to use.

Regards,

Leen Toelen

Leen Toelen