< 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 >