Search code examples
eclipseserviceosgi

When do multiple distinct ServiceReferences refer to a same ServiceRegistration?


As documented in org.osgi.framework.ServiceReference :

Every service registered in the Framework has a unique ServiceRegistration object and may have multiple, distinct ServiceReference objects referring to it.

But Eclipse's implementation org.eclipse.osgi.internal.serviceregistry.ServiceReferenceImpl :

public class ServiceReferenceImpl<S> implements ServiceReference<S> {
    /** Registered Service object. */
    private final ServiceRegistrationImpl<S> registration;

    /**
     * Construct a reference.
     *
     */
    ServiceReferenceImpl(ServiceRegistrationImpl<S> registration) {
        this.registration = registration;
        /* We must not dereference registration in the constructor
         * since it is "leaked" to us in the ServiceRegistrationImpl
         * constructor.
         */
    }

    ...
}

Its constructor has default access, and it is called only in the constructor of org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl<S> :

public class ServiceRegistrationImpl<S> implements ServiceRegistration<S>, Comparable<ServiceRegistrationImpl<?>> {

    /** Reference to this registration. */
    /* @GuardedBy("registrationLock") */
    private ServiceReferenceImpl<S> reference;

    /**
     * Construct a ServiceRegistration and register the service
     * in the framework's service registry.
     *
     */
    ServiceRegistrationImpl(ServiceRegistry registry, BundleContextImpl context, String[] clazzes, S service) {
        this.registry = registry;
        this.context = context;
        this.bundle = context.getBundleImpl();
        this.clazzes = clazzes; /* must be set before calling createProperties. */
        this.service = service; /* must be set before calling createProperties. */
        this.serviceid = registry.getNextServiceId(); /* must be set before calling createProperties. */
        this.contextsUsing = new ArrayList<>(10);

        synchronized (registrationLock) {
            this.state = REGISTERED;
            /* We leak this from the constructor here, but it is ok
             * because the ServiceReferenceImpl constructor only
             * stores the value in a final field without
             * otherwise using it.
             */
            this.reference = new ServiceReferenceImpl<>(this);
        }
    }
    ...
}

In addition, the org.osgi.framework.ServiceRegistration interface only has a getReference() method, not a method like getReferences().

So I'm confused about when are there multiple distinct ServiceReferences referencing a same ServiceRegistration ?


Solution

  • It is up to the implementation. Some will use a single shared ServiceReference object per ServiceRegistration. Others can use multiple. The point of the caution in the spec is for code to not rely on identity to determine if two ServiceReferences refer to the same ServiceRegistration.