> Consider the following code:
> 
> // BundleContext bc ...
> 
> final ServiceReference[] refs =
>   bc.getServiceReferences( SomeType.class.getName(),
>                            "(foo=bar)" );
> if ( null != refs )
>    for ( ServiceReference ref: refs ) {
>       final SomeType st = (SomeType) bc.getService( ref );
>       try {
>          if ( null != st )
>            return st.use( 42 );
>       } catch (NullPointerException ignored) {
>          // Ignore it, as the service went away.
>       } finally {
>         bc.ungetService( ref );
>       }
>    }
> 
> 
> Here we grab all known ServiceReferences for a given object class and
> filter, walk the set, and attempt to call on the first valid
> reference.
> 
> We attempt to catch a NPE that might arise from the "st.use( 42 )"
> call if the object referenced by "st" were to disappear immediately
> after the null check but before we could call call its use() method.
> 
> Several questions:
> 
> o Could this NPE actually arise here, or is "st" pinned in memory by
>   the reference we're holding to it?

The NPE can not occur because "st" is NULL.  You have a local copy of the
service, there is no way for the OSGi service registry to null out your 
copy of the service.  It is possible that the implementation of 
st.use would throw an exception if the service was unregistered.

> 
> o Is the preceding null test then spurious?

This null check is needed because the service associated with a 
ServiceReference in the refs array may have been unregistered since the 
called to getServiceReferences.

> 
> o Should I bother with BundleContext.ungetService() if
>   BundleContext.getService() had returned null?

No, there is no need to call ungetService if you were not successful
in getting the service object.  Doing so may cause accounting 
errors for ServiceFactory services.  If a bundle calls ungetService for a 
ServiceReference object more times that the success number of 
getService calls then the framework will think the bundle is done with 
the service before it actually is.  This will cause the call to
ServiceFactory.ungetService(Bundle, ServiceRegistration, Object)
to happen too early.

Hope that helps.

Tom
_______________________________________________
OSGi Developer Mail List
[email protected]
http://www2.osgi.org/mailman/listinfo/osgi-dev

Reply via email to