< prev index next >
src/java.base/share/classes/java/util/ServiceLoader.java
Print this page
@@ -117,11 +117,11 @@
*
* <p> An application or library using this loading facility and developed
* and deployed as an explicit module must have an appropriate <i>uses</i>
* clause in its <i>module descriptor</i> to declare that the module uses
* implementations of the service. A corresponding requirement is that a
- * provider deployed as a named module must have an appropriate
+ * provider deployed as an explicit module must have an appropriate
* <i>provides</i> clause in its module descriptor to declare that the module
* provides an implementation of the service. The <i>uses</i> and
* <i>provides</i> allow consumers of a service to be <i>linked</i> to modules
* containing providers of the service.
*
@@ -201,12 +201,15 @@
* all providers in that layer are located, irrespective of their class
* loader. The ordering of modules defined to the same class loader, or the
* ordering of modules in a layer, is not defined. </li>
*
* <li> If a named module declares more than one provider then the providers
- * are located in the order that they appear in the {@code provides} table of
- * the {@code Module} class file attribute ({@code module-info.class}). </li>
+ * are located in the iteration order of the {@link
+ * java.lang.module.ModuleDescriptor.Provides#providers() providers} list.
+ * Providers added dynamically by instrumentation agents ({@link
+ * java.lang.instrument.Instrumentation#redefineModule redefineModule})
+ * are always located after providers declared by the module. </li>
*
* <li> When locating providers in unnamed modules then the ordering is
* based on the order that the class loader's {@link
* ClassLoader#getResources(String) ClassLoader.getResources(String)}
* method finds the service configuration files. </li>
@@ -333,10 +336,12 @@
* @param <S>
* The type of the service to be loaded by this loader
*
* @author Mark Reinhold
* @since 1.6
+ * @revised 9
+ * @spec JPMS
*/
public final class ServiceLoader<S>
implements Iterable<S>
{
@@ -384,10 +389,11 @@
* to select or filter on the provider class without instantiating the
* provider. </p>
*
* @param <S> The service type
* @since 9
+ * @spec JPMS
*/
public static interface Provider<S> extends Supplier<S> {
/**
* Returns the provider type. There is no guarantee that this type is
* accessible or that it has a public no-args constructor. The {@link
@@ -925,30 +931,32 @@
if (loader == null) {
catalog = BootLoader.getServicesCatalog();
} else {
catalog = ServicesCatalog.getServicesCatalogOrNull(loader);
}
- Stream<ServiceProvider> stream1;
+ List<ServiceProvider> providers;
if (catalog == null) {
- stream1 = Stream.empty();
+ providers = List.of();
} else {
- stream1 = catalog.findServices(serviceName).stream();
+ providers = catalog.findServices(serviceName);
}
// modules in custom layers that define modules to the class loader
- Stream<ServiceProvider> stream2;
if (loader == null) {
- stream2 = Stream.empty();
+ return providers.iterator();
} else {
+ List<ServiceProvider> allProviders = new ArrayList<>(providers);
Layer bootLayer = Layer.boot();
- stream2 = JLRM_ACCESS.layers(loader)
- .filter(l -> (l != bootLayer))
- .map(l -> providers(l))
- .flatMap(List::stream);
+ Iterator<Layer> iterator = JLRM_ACCESS.layers(loader).iterator();
+ while (iterator.hasNext()) {
+ Layer layer = iterator.next();
+ if (layer != bootLayer) {
+ allProviders.addAll(providers(layer));
+ }
+ }
+ return allProviders.iterator();
}
-
- return Stream.concat(stream1, stream2).iterator();
}
@Override
public boolean hasNext() {
// already have the next provider cached
@@ -1212,10 +1220,13 @@
* Invoking its {@link java.util.Iterator#remove() remove} method will
* cause an {@link UnsupportedOperationException} to be thrown.
*
* @return An iterator that lazily loads providers for this loader's
* service
+ *
+ * @revised 9
+ * @spec JPMS
*/
public Iterator<S> iterator() {
// create lookup iterator if needed
if (lookupIterator1 == null) {
@@ -1277,12 +1288,14 @@
* thrown when locating the provider then it is wrapped with a {@code
* ServiceConfigurationError} and thrown by whatever method caused the
* provider to be loaded. </p>
*
* <p> If this loader's provider caches are cleared by invoking the {@link
- * #reload() reload} method then existing streams for this service
- * loader should be discarded. </p>
+ * #reload() reload} method then existing streams for this service loader
+ * should be discarded. The returned stream's source {@code Spliterator} is
+ * <em>fail-fast</em> and will throw {@link ConcurrentModificationException}
+ * if the provider cache has been cleared. </p>
*
* <p> The following examples demonstrate usage. The first example
* creates a stream of providers, the second example is the same except
* that it sorts the providers by provider class name (and so locate all
* providers).
@@ -1298,10 +1311,11 @@
* }</pre>
*
* @return A stream that lazily loads providers for this loader's service
*
* @since 9
+ * @spec JPMS
*/
public Stream<Provider<S>> stream() {
// use cached providers as the source when all providers loaded
if (loadedAllProviders) {
return loadedProviders.stream();
@@ -1412,10 +1426,13 @@
*
* @throws ServiceConfigurationError
* if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
+ *
+ * @revised 9
+ * @spec JPMS
*/
@CallerSensitive
public static <S> ServiceLoader<S> load(Class<S> service,
ClassLoader loader)
{
@@ -1455,10 +1472,13 @@
*
* @throws ServiceConfigurationError
* if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
+ *
+ * @revised 9
+ * @spec JPMS
*/
@CallerSensitive
public static <S> ServiceLoader<S> load(Class<S> service) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
@@ -1488,10 +1508,13 @@
*
* @throws ServiceConfigurationError
* if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
+ *
+ * @revised 9
+ * @spec JPMS
*/
@CallerSensitive
public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
ClassLoader cl = ClassLoader.getPlatformClassLoader();
return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
@@ -1520,10 +1543,11 @@
* if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
*
* @since 9
+ * @spec JPMS
*/
@CallerSensitive
public static <S> ServiceLoader<S> load(Layer layer, Class<S> service) {
return new ServiceLoader<>(Reflection.getCallerClass(), layer, service);
}
@@ -1549,10 +1573,11 @@
* appropriate static factory method or constructor, can't be
* assigned to the service type, or if any other kind of exception
* or error is thrown when locating or instantiating the provider.
*
* @since 9
+ * @spec JPMS
*/
public Optional<S> findFirst() {
Iterator<S> iterator = iterator();
if (iterator.hasNext()) {
return Optional.of(iterator.next());
< prev index next >