Showing changes in java/12/java.base/java/util/ServiceLoader.java (new version) from java/8/java/util/ServiceLoader.java (old version). +1,603 -340
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this
  * particular file as subject to the "Classpath" exception as provided
  * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
  *
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
 package java.util;
 
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.net.URL;
-import java.security.AccessController;
+import java.net.URLConnection;
 import java.security.AccessControlContext;
+import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import jdk.internal.loader.BootLoader;
+import jdk.internal.loader.ClassLoaders;
+import jdk.internal.access.JavaLangAccess;
+import jdk.internal.access.SharedSecrets;
+import jdk.internal.misc.VM;
+import jdk.internal.module.ServicesCatalog;
+import jdk.internal.module.ServicesCatalog.ServiceProvider;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
 
 
 /**
- * A simple service-provider loading facility.
+ * A facility to load implementations of a service.
  *
- * <p> A <i>service</i> is a well-known set of interfaces and (usually
- * abstract) classes.  A <i>service provider</i> is a specific implementation
- * of a service.  The classes in a provider typically implement the interfaces
- * and subclass the classes defined in the service itself.  Service providers
- * can be installed in an implementation of the Java platform in the form of
- * extensions, that is, jar files placed into any of the usual extension
- * directories.  Providers can also be made available by adding them to the
- * application's class path or by some other platform-specific means.
+ * <p> A <i>service</i> is a well-known interface or class for which zero, one,
+ * or many service providers exist. A <i>service provider</i> (or just
+ * <i>provider</i>) is a class that implements or subclasses the well-known
+ * interface or class. A {@code ServiceLoader} is an object that locates and
+ * loads service providers deployed in the run time environment at a time of an
+ * application's choosing. Application code refers only to the service, not to
+ * service providers, and is assumed to be capable of choosing between multiple
+ * service providers (based on the functionality they expose through the service),
+ * and handling the possibility that no service providers are located.
  *
- * <p> For the purpose of loading, a service is represented by a single type,
- * that is, a single interface or abstract class.  (A concrete class can be
- * used, but this is not recommended.)  A provider of a given service contains
- * one or more concrete classes that extend this <i>service type</i> with data
- * and code specific to the provider.  The <i>provider class</i> is typically
- * not the entire provider itself but rather a proxy which contains enough
- * information to decide whether the provider is able to satisfy a particular
- * request together with code that can create the actual provider on demand.
- * The details of provider classes tend to be highly service-specific; no
- * single class or interface could possibly unify them, so no such type is
- * defined here.  The only requirement enforced by this facility is that
- * provider classes must have a zero-argument constructor so that they can be
- * instantiated during loading.
+ * <h3> Obtaining a service loader </h3>
  *
- * <p><a name="format"> A service provider is identified by placing a
- * <i>provider-configuration file</i> in the resource directory
- * <tt>META-INF/services</tt>.</a>  The file's name is the fully-qualified <a
- * href="../lang/ClassLoader.html#name">binary name</a> of the service's type.
- * The file contains a list of fully-qualified binary names of concrete
- * provider classes, one per line.  Space and tab characters surrounding each
- * name, as well as blank lines, are ignored.  The comment character is
- * <tt>'#'</tt> (<tt>'&#92;u0023'</tt>,
- * <font style="font-size:smaller;">NUMBER SIGN</font>); on
- * each line all characters following the first comment character are ignored.
- * The file must be encoded in UTF-8.
+ * <p> An application obtains a service loader for a given service by invoking
+ * one of the static {@code load} methods of {@code ServiceLoader}. If the
+ * application is a module, then its module declaration must have a <i>uses</i>
+ * directive that specifies the service; this helps to locate providers and ensure
+ * they will execute reliably. In addition, if the application module does not
+ * contain the service, then its module declaration must have a <i>requires</i>
+ * directive that specifies the module which exports the service. It is strongly
+ * recommended that the application module does <b>not</b> require modules which
+ * contain providers of the service.
  *
- * <p> If a particular concrete provider class is named in more than one
- * configuration file, or is named in the same configuration file more than
- * once, then the duplicates are ignored.  The configuration file naming a
- * particular provider need not be in the same jar file or other distribution
- * unit as the provider itself.  The provider must be accessible from the same
- * class loader that was initially queried to locate the configuration file;
- * note that this is not necessarily the class loader from which the file was
- * actually loaded.
+ * <p> A service loader can be used to locate and instantiate providers of the
+ * service by means of the {@link #iterator() iterator} method. {@code ServiceLoader}
+ * also defines the {@link #stream() stream} method to obtain a stream of providers
+ * that can be inspected and filtered without instantiating them.
  *
- * <p> Providers are located and instantiated lazily, that is, on demand.  A
- * service loader maintains a cache of the providers that have been loaded so
- * far.  Each invocation of the {@link #iterator iterator} method returns an
- * iterator that first yields all of the elements of the cache, in
+ * <p> As an example, suppose the service is {@code com.example.CodecFactory}, an
+ * interface that defines methods for producing encoders and decoders:
+ *
+ * <pre>{@code
+ *     package com.example;
+ *     public interface CodecFactory {
+ *         Encoder getEncoder(String encodingName);
+ *         Decoder getDecoder(String encodingName);
+ *     }
+ * }</pre>
+ *
+ * <p> The following code obtains a service loader for the {@code CodecFactory}
+ * service, then uses its iterator (created automatically by the enhanced-for
+ * loop) to yield instances of the service providers that are located:
+ *
+ * <pre>{@code
+ *     ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
+ *     for (CodecFactory factory : loader) {
+ *         Encoder enc = factory.getEncoder("PNG");
+ *         if (enc != null)
+ *             ... use enc to encode a PNG file
+ *             break;
+ *         }
+ * }</pre>
+ *
+ * <p> If this code resides in a module, then in order to refer to the
+ * {@code com.example.CodecFactory} interface, the module declaration would
+ * require the module which exports the interface. The module declaration would
+ * also specify use of {@code com.example.CodecFactory}:
+ * <pre>{@code
+ *     requires com.example.codec.core;
+ *     uses com.example.CodecFactory;
+ * }</pre>
+ *
+ * <p> Sometimes an application may wish to inspect a service provider before
+ * instantiating it, in order to determine if an instance of that service
+ * provider would be useful. For example, a service provider for {@code
+ * CodecFactory} that is capable of producing a "PNG" encoder may be annotated
+ * with {@code @PNG}. The following code uses service loader's {@code stream}
+ * method to yield instances of {@code Provider<CodecFactory>} in contrast to
+ * how the iterator yields instances of {@code CodecFactory}:
+ * <pre>{@code
+ *     ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
+ *     Set<CodecFactory> pngFactories = loader
+ *            .stream()                                              // Note a below
+ *            .filter(p -> p.type().isAnnotationPresent(PNG.class))  // Note b
+ *            .map(Provider::get)                                    // Note c
+ *            .collect(Collectors.toSet());
+ * }</pre>
+ * <ol type="a">
+ *   <li> A stream of {@code Provider<CodecFactory>} objects </li>
+ *   <li> {@code p.type()} yields a {@code Class<CodecFactory>} </li>
+ *   <li> {@code get()} yields an instance of {@code CodecFactory} </li>
+ * </ol>
+ *
+ * <h3> Designing services </h3>
+ *
+ * <p> A service is a single type, usually an interface or abstract class. A
+ * concrete class can be used, but this is not recommended. The type may have
+ * any accessibility. The methods of a service are highly domain-specific, so
+ * this API specification cannot give concrete advice about their form or
+ * function. However, there are two general guidelines:
+ * <ol>
+ *   <li><p> A service should declare as many methods as needed to allow service
+ *   providers to communicate their domain-specific properties and other
+ *   quality-of-implementation factors. An application which obtains a service
+ *   loader for the service may then invoke these methods on each instance of
+ *   a service provider, in order to choose the best provider for the
+ *   application. </p></li>
+ *   <li><p> A service should express whether its service providers are intended
+ *   to be direct implementations of the service or to be an indirection
+ *   mechanism such as a "proxy" or a "factory". Service providers tend to be
+ *   indirection mechanisms when domain-specific objects are relatively
+ *   expensive to instantiate; in this case, the service should be designed
+ *   so that service providers are abstractions which create the "real"
+ *   implementation on demand. For example, the {@code CodecFactory} service
+ *   expresses through its name that its service providers are factories
+ *   for codecs, rather than codecs themselves, because it may be expensive
+ *   or complicated to produce certain codecs. </p></li>
+ * </ol>
+ *
+ * <h3> <a id="developing-service-providers">Developing service providers</a> </h3>
+ *
+ * <p> A service provider is a single type, usually a concrete class. An
+ * interface or abstract class is permitted because it may declare a static
+ * provider method, discussed later. The type must be public and must not be
+ * an inner class.
+ *
+ * <p> A service provider and its supporting code may be developed in a module,
+ * which is then deployed on the application module path or in a modular
+ * image. Alternatively, a service provider and its supporting code may be
+ * packaged as a JAR file and deployed on the application class path. The
+ * advantage of developing a service provider in a module is that the provider
+ * can be fully encapsulated to hide all details of its implementation.
+ *
+ * <p> An application that obtains a service loader for a given service is
+ * indifferent to whether providers of the service are deployed in modules or
+ * packaged as JAR files. The application instantiates service providers via
+ * the service loader's iterator, or via {@link Provider Provider} objects in
+ * the service loader's stream, without knowledge of the service providers'
+ * locations.
+ *
+ * <h3> Deploying service providers as modules </h3>
+ *
+ * <p> A service provider that is developed in a module must be specified in a
+ * <i>provides</i> directive in the module declaration. The provides directive
+ * specifies both the service and the service provider; this helps to locate the
+ * provider when another module, with a <i>uses</i> directive for the service,
+ * obtains a service loader for the service. It is strongly recommended that the
+ * module does not export the package containing the service provider. There is
+ * no support for a module specifying, in a <i>provides</i> directive, a service
+ * provider in another module.
+
+ * <p> A service provider that is developed in a module has no control over when
+ * it is instantiated, since that occurs at the behest of the application, but it
+ * does have control over how it is instantiated:
+ *
+ * <ul>
+ *
+ *   <li> If the service provider declares a provider method, then the service
+ *   loader invokes that method to obtain an instance of the service provider. A
+ *   provider method is a public static method named "provider" with no formal
+ *   parameters and a return type that is assignable to the service's interface
+ *   or class.
+ *   <p> In this case, the service provider itself need not be assignable to the
+ *   service's interface or class. </li>
+ *
+ *   <li> If the service provider does not declare a provider method, then the
+ *   service provider is instantiated directly, via its provider constructor. A
+ *   provider constructor is a public constructor with no formal parameters.
+ *   <p> In this case, the service provider must be assignable to the service's
+ *   interface or class </li>
+ *
+ * </ul>
+ *
+ * <p> A service provider that is deployed as an
+ * {@linkplain java.lang.module.ModuleDescriptor#isAutomatic automatic module} on
+ * the application module path must have a provider constructor. There is no
+ * support for a provider method in this case.
+ *
+ * <p> As an example, suppose a module specifies the following directives:
+ * <pre>{@code
+ *     provides com.example.CodecFactory with com.example.impl.StandardCodecs;
+ *     provides com.example.CodecFactory with com.example.impl.ExtendedCodecsFactory;
+ * }</pre>
+ *
+ * <p> where
+ *
+ * <ul>
+ *   <li> {@code com.example.CodecFactory} is the two-method service from
+ *   earlier. </li>
+ *
+ *   <li> {@code com.example.impl.StandardCodecs} is a public class that implements
+ *   {@code CodecFactory} and has a public no-args constructor. </li>
+ *
+ *   <li> {@code com.example.impl.ExtendedCodecsFactory} is a public class that
+ *   does not implement CodecFactory, but it declares a public static no-args
+ *   method named "provider" with a return type of {@code CodecFactory}. </li>
+ * </ul>
+ *
+ * <p> A service loader will instantiate {@code StandardCodecs} via its
+ * constructor, and will instantiate {@code ExtendedCodecsFactory} by invoking
+ * its {@code provider} method. The requirement that the provider constructor or
+ * provider method is public helps to document the intent that the class (that is,
+ * the service provider) will be instantiated by an entity (that is, a service
+ * loader) which is outside the class's package.
+ *
+ * <h3> Deploying service providers on the class path </h3>
+ *
+ * A service provider that is packaged as a JAR file for the class path is
+ * identified by placing a <i>provider-configuration file</i> in the resource
+ * directory {@code META-INF/services}. The name of the provider-configuration
+ * file is the fully qualified binary name of the service. The provider-configuration
+ * file contains a list of fully qualified binary names of service providers, one
+ * per line.
+ *
+ * <p> For example, suppose the service provider
+ * {@code com.example.impl.StandardCodecs} is packaged in a JAR file for the
+ * class path. The JAR file will contain a provider-configuration file named:
+ *
+ * <blockquote>{@code
+ *     META-INF/services/com.example.CodecFactory
+ * }</blockquote>
+ *
+ * that contains the line:
+ *
+ * <blockquote>{@code
+ *     com.example.impl.StandardCodecs # Standard codecs
+ * }</blockquote>
+ *
+ * <p><a id="format">The provider-configuration file must be encoded in UTF-8. </a>
+ * Space and tab characters surrounding each service provider's name, as well as
+ * blank lines, are ignored. The comment character is {@code '#'}
+ * ({@code '&#92;u0023'} <span style="font-size:smaller;">NUMBER SIGN</span>);
+ * on each line all characters following the first comment character are ignored.
+ * If a service provider class name is listed more than once in a
+ * provider-configuration file then the duplicate is ignored. If a service
+ * provider class is named in more than one configuration file then the duplicate
+ * is ignored.
+ *
+ * <p> A service provider that is mentioned in a provider-configuration file may
+ * be located in the same JAR file as the provider-configuration file or in a
+ * different JAR file. The service provider must be visible from the class loader
+ * that is initially queried to locate the provider-configuration file; this is
+ * not necessarily the class loader which ultimately locates the
+ * provider-configuration file.
+ *
+ * <h3> Timing of provider discovery </h3>
+ *
+ * <p> Service providers are loaded and instantiated lazily, that is, on demand.
+ * A service loader maintains a cache of the providers that have been loaded so
+ * far. Each invocation of the {@code iterator} method returns an {@code Iterator}
+ * that first yields all of the elements cached from previous iteration, in
  * instantiation order, and then lazily locates and instantiates any remaining
- * providers, adding each one to the cache in turn.  The cache can be cleared
- * via the {@link #reload reload} method.
+ * providers, adding each one to the cache in turn. Similarly, each invocation
+ * of the stream method returns a {@code Stream} that first processes all
+ * providers loaded by previous stream operations, in load order, and then lazily
+ * locates any remaining providers. Caches are cleared via the {@link #reload
+ * reload} method.
  *
- * <p> Service loaders always execute in the security context of the caller.
+ * <h3> <a id="errors">Errors</a> </h3>
+ *
+ * <p> When using the service loader's {@code iterator}, the {@link
+ * Iterator#hasNext() hasNext} and {@link Iterator#next() next} methods will
+ * fail with {@link ServiceConfigurationError} if an error occurs locating,
+ * loading or instantiating a service provider. When processing the service
+ * loader's stream then {@code ServiceConfigurationError} may be thrown by any
+ * method that causes a service provider to be located or loaded.
+ *
+ * <p> When loading or instantiating a service provider in a module, {@code
+ * ServiceConfigurationError} can be thrown for the following reasons:
+ *
+ * <ul>
+ *
+ *   <li> The service provider cannot be loaded. </li>
+ *
+ *   <li> The service provider does not declare a provider method, and either
+ *   it is not assignable to the service's interface/class or does not have a
+ *   provider constructor. </li>
+ *
+ *   <li> The service provider declares a public static no-args method named
+ *   "provider" with a return type that is not assignable to the service's
+ *   interface or class. </li>
+ *
+ *   <li> The service provider class file has more than one public static
+ *   no-args method named "{@code provider}". </li>
+ *
+ *   <li> The service provider declares a provider method and it fails by
+ *   returning {@code null} or throwing an exception. </li>
+ *
+ *   <li> The service provider does not declare a provider method, and its
+ *   provider constructor fails by throwing an exception. </li>
+ *
+ * </ul>
+ *
+ * <p> When reading a provider-configuration file, or loading or instantiating
+ * a provider class named in a provider-configuration file, then {@code
+ * ServiceConfigurationError} can be thrown for the following reasons:
+ *
+ * <ul>
+ *
+ *   <li> The format of the provider-configuration file violates the <a
+ *   href="ServiceLoader.html#format">format</a> specified above; </li>
+ *
+ *   <li> An {@link IOException IOException} occurs while reading the
+ *   provider-configuration file; </li>
+ *
+ *   <li> A service provider cannot be loaded; </li>
+ *
+ *   <li> A service provider is not assignable to the service's interface or
+ *   class, or does not define a provider constructor, or cannot be
+ *   instantiated. </li>
+ *
+ * </ul>
+ *
+ * <h3> Security </h3>
+ *
+ * <p> Service loaders always execute in the security context of the caller
+ * of the iterator or stream methods and may also be restricted by the security
+ * context of the caller that created the service loader.
  * Trusted system code should typically invoke the methods in this class, and
  * the methods of the iterators which they return, from within a privileged
  * security context.
  *
+ * <h3> Concurrency </h3>
+ *
  * <p> Instances of this class are not safe for use by multiple concurrent
  * threads.
  *
- * <p> Unless otherwise specified, passing a <tt>null</tt> argument to any
+ * <h3> Null handling </h3>
+ *
+ * <p> Unless otherwise specified, passing a {@code null} argument to any
  * method in this class will cause a {@link NullPointerException} to be thrown.
  *
- *
- * <p><span style="font-weight: bold; padding-right: 1em">Example</span>
- * Suppose we have a service type <tt>com.example.CodecSet</tt> which is
- * intended to represent sets of encoder/decoder pairs for some protocol.  In
- * this case it is an abstract class with two abstract methods:
- *
- * <blockquote><pre>
- * public abstract Encoder getEncoder(String encodingName);
- * public abstract Decoder getDecoder(String encodingName);</pre></blockquote>
- *
- * Each method returns an appropriate object or <tt>null</tt> if the provider
- * does not support the given encoding.  Typical providers support more than
- * one encoding.
- *
- * <p> If <tt>com.example.impl.StandardCodecs</tt> is an implementation of the
- * <tt>CodecSet</tt> service then its jar file also contains a file named
- *
- * <blockquote><pre>
- * META-INF/services/com.example.CodecSet</pre></blockquote>
- *
- * <p> This file contains the single line:
- *
- * <blockquote><pre>
- * com.example.impl.StandardCodecs    # Standard codecs</pre></blockquote>
- *
- * <p> The <tt>CodecSet</tt> class creates and saves a single service instance
- * at initialization:
- *
- * <blockquote><pre>
- * private static ServiceLoader&lt;CodecSet&gt; codecSetLoader
- *     = ServiceLoader.load(CodecSet.class);</pre></blockquote>
- *
- * <p> To locate an encoder for a given encoding name it defines a static
- * factory method which iterates through the known and available providers,
- * returning only when it has located a suitable encoder or has run out of
- * providers.
- *
- * <blockquote><pre>
- * public static Encoder getEncoder(String encodingName) {
- *     for (CodecSet cp : codecSetLoader) {
- *         Encoder enc = cp.getEncoder(encodingName);
- *         if (enc != null)
- *             return enc;
- *     }
- *     return null;
- * }</pre></blockquote>
- *
- * <p> A <tt>getDecoder</tt> method is defined similarly.
- *
- *
- * <p><span style="font-weight: bold; padding-right: 1em">Usage Note</span> If
- * the class path of a class loader that is used for provider loading includes
- * remote network URLs then those URLs will be dereferenced in the process of
- * searching for provider-configuration files.
- *
- * <p> This activity is normal, although it may cause puzzling entries to be
- * created in web-server logs.  If a web server is not configured correctly,
- * however, then this activity may cause the provider-loading algorithm to fail
- * spuriously.
- *
- * <p> A web server should return an HTTP 404 (Not Found) response when a
- * requested resource does not exist.  Sometimes, however, web servers are
- * erroneously configured to return an HTTP 200 (OK) response along with a
- * helpful HTML error page in such cases.  This will cause a {@link
- * ServiceConfigurationError} to be thrown when this class attempts to parse
- * the HTML page as a provider-configuration file.  The best solution to this
- * problem is to fix the misconfigured web server to return the correct
- * response code (HTTP 404) along with the HTML error page.
- *
  * @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>
 {
-
-    private static final String PREFIX = "META-INF/services/";
-
     // The class or interface representing the service being loaded
     private final Class<S> service;
 
-    // The class loader used to locate, load, and instantiate providers
+    // The class of the service type
+    private final String serviceName;
+
+    // The module layer used to locate providers; null when locating
+    // providers using a class loader
+    private final ModuleLayer layer;
+
+    // The class loader used to locate, load, and instantiate providers;
+    // null when locating provider using a module layer
     private final ClassLoader loader;
 
     // The access control context taken when the ServiceLoader is created
     private final AccessControlContext acc;
 
-    // Cached providers, in instantiation order
-    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
+    // The lazy-lookup iterator for iterator operations
+    private Iterator<Provider<S>> lookupIterator1;
+    private final List<S> instantiatedProviders = new ArrayList<>();
 
-    // The current lazy-lookup iterator
-    private LazyIterator lookupIterator;
+    // The lazy-lookup iterator for stream operations
+    private Iterator<Provider<S>> lookupIterator2;
+    private final List<Provider<S>> loadedProviders = new ArrayList<>();
+    private boolean loadedAllProviders; // true when all providers loaded
 
-    /**
-     * Clear this loader's provider cache so that all providers will be
-     * reloaded.
-     *
-     * <p> After invoking this method, subsequent invocations of the {@link
-     * #iterator() iterator} method will lazily look up and instantiate
-     * providers from scratch, just as is done by a newly-created loader.
-     *
-     * <p> This method is intended for use in situations in which new providers
-     * can be installed into a running Java virtual machine.
-     */
-    public void reload() {
-        providers.clear();
-        lookupIterator = new LazyIterator(service, loader);
+    // Incremented when reload is called
+    private int reloadCount;
+
+    private static JavaLangAccess LANG_ACCESS;
+    static {
+        LANG_ACCESS = SharedSecrets.getJavaLangAccess();
     }
 
-    private ServiceLoader(Class<S> svc, ClassLoader cl) {
-        service = Objects.requireNonNull(svc, "Service interface cannot be null");
-        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
-        acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
-        reload();
+    /**
+     * Represents a service provider located by {@code ServiceLoader}.
+     *
+     * <p> When using a loader's {@link ServiceLoader#stream() stream()} method
+     * then the elements are of type {@code Provider}. This allows processing
+     * 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
+         * #get() get()} method should be used to obtain the provider instance.
+         *
+         * <p> When a module declares that the provider class is created by a
+         * provider factory then this method returns the return type of its
+         * public static "{@code provider()}" method.
+         *
+         * @return The provider type
+         */
+        Class<? extends S> type();
+
+        /**
+         * Returns an instance of the provider.
+         *
+         * @return An instance of the provider.
+         *
+         * @throws ServiceConfigurationError
+         *         If the service provider cannot be instantiated, or in the
+         *         case of a provider factory, the public static
+         *         "{@code provider()}" method returns {@code null} or throws
+         *         an error or exception. The {@code ServiceConfigurationError}
+         *         will carry an appropriate cause where possible.
+         */
+        @Override S get();
+    }
+
+    /**
+     * Initializes a new instance of this class for locating service providers
+     * in a module layer.
+     *
+     * @throws ServiceConfigurationError
+     *         If {@code svc} is not accessible to {@code caller} or the caller
+     *         module does not use the service type.
+     */
+    private ServiceLoader(Class<?> caller, ModuleLayer layer, Class<S> svc) {
+        Objects.requireNonNull(caller);
+        Objects.requireNonNull(layer);
+        Objects.requireNonNull(svc);
+        checkCaller(caller, svc);
+
+        this.service = svc;
+        this.serviceName = svc.getName();
+        this.layer = layer;
+        this.loader = null;
+        this.acc = (System.getSecurityManager() != null)
+                ? AccessController.getContext()
+                : null;
+    }
+
+    /**
+     * Initializes a new instance of this class for locating service providers
+     * via a class loader.
+     *
+     * @throws ServiceConfigurationError
+     *         If {@code svc} is not accessible to {@code caller} or the caller
+     *         module does not use the service type.
+     */
+    private ServiceLoader(Class<?> caller, Class<S> svc, ClassLoader cl) {
+        Objects.requireNonNull(svc);
+
+        if (VM.isBooted()) {
+            checkCaller(caller, svc);
+            if (cl == null) {
+                cl = ClassLoader.getSystemClassLoader();
+            }
+        } else {
+
+            // if we get here then it means that ServiceLoader is being used
+            // before the VM initialization has completed. At this point then
+            // only code in the java.base should be executing.
+            Module callerModule = caller.getModule();
+            Module base = Object.class.getModule();
+            Module svcModule = svc.getModule();
+            if (callerModule != base || svcModule != base) {
+                fail(svc, "not accessible to " + callerModule + " during VM init");
+            }
+
+            // restricted to boot loader during startup
+            cl = null;
+        }
+
+        this.service = svc;
+        this.serviceName = svc.getName();
+        this.layer = null;
+        this.loader = cl;
+        this.acc = (System.getSecurityManager() != null)
+                ? AccessController.getContext()
+                : null;
+    }
+
+    /**
+     * Initializes a new instance of this class for locating service providers
+     * via a class loader.
+     *
+     * @apiNote For use by ResourceBundle
+     *
+     * @throws ServiceConfigurationError
+     *         If the caller module does not use the service type.
+     */
+    private ServiceLoader(Module callerModule, Class<S> svc, ClassLoader cl) {
+        if (!callerModule.canUse(svc)) {
+            fail(svc, callerModule + " does not declare `uses`");
+        }
+
+        this.service = Objects.requireNonNull(svc);
+        this.serviceName = svc.getName();
+        this.layer = null;
+        this.loader = cl;
+        this.acc = (System.getSecurityManager() != null)
+                ? AccessController.getContext()
+                : null;
+    }
+
+    /**
+     * Checks that the given service type is accessible to types in the given
+     * module, and check that the module declares that it uses the service type.
+     */
+    private static void checkCaller(Class<?> caller, Class<?> svc) {
+        if (caller == null) {
+            fail(svc, "no caller to check if it declares `uses`");
+        }
+
+        // Check access to the service type
+        Module callerModule = caller.getModule();
+        int mods = svc.getModifiers();
+        if (!Reflection.verifyMemberAccess(caller, svc, null, mods)) {
+            fail(svc, "service type not accessible to " + callerModule);
+        }
+
+        // If the caller is in a named module then it should "uses" the
+        // service type
+        if (!callerModule.canUse(svc)) {
+            fail(svc, callerModule + " does not declare `uses`");
+        }
     }
 
     private static void fail(Class<?> service, String msg, Throwable cause)
         throws ServiceConfigurationError
     {
         throw new ServiceConfigurationError(service.getName() + ": " + msg,
                                             cause);
     }
 
     private static void fail(Class<?> service, String msg)
         throws ServiceConfigurationError
     {
         throw new ServiceConfigurationError(service.getName() + ": " + msg);
     }
 
     private static void fail(Class<?> service, URL u, int line, String msg)
         throws ServiceConfigurationError
     {
         fail(service, u + ":" + line + ": " + msg);
     }
 
-    // Parse a single line from the given configuration file, adding the name
-    // on the line to the names list.
-    //
-    private int parseLine(Class<?> service, URL u, BufferedReader r, int lc,
-                          List<String> names)
-        throws IOException, ServiceConfigurationError
-    {
-        String ln = r.readLine();
-        if (ln == null) {
-            return -1;
-        }
-        int ci = ln.indexOf('#');
-        if (ci >= 0) ln = ln.substring(0, ci);
-        ln = ln.trim();
-        int n = ln.length();
-        if (n != 0) {
-            if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
-                fail(service, u, lc, "Illegal configuration-file syntax");
-            int cp = ln.codePointAt(0);
-            if (!Character.isJavaIdentifierStart(cp))
-                fail(service, u, lc, "Illegal provider-class name: " + ln);
-            for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
-                cp = ln.codePointAt(i);
-                if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
-                    fail(service, u, lc, "Illegal provider-class name: " + ln);
-            }
-            if (!providers.containsKey(ln) && !names.contains(ln))
-                names.add(ln);
-        }
-        return lc + 1;
+    /**
+     * Returns {@code true} if the provider is in an explicit module
+     */
+    private boolean inExplicitModule(Class<?> clazz) {
+        Module module = clazz.getModule();
+        return module.isNamed() && !module.getDescriptor().isAutomatic();
     }
 
-    // Parse the content of the given URL as a provider-configuration file.
-    //
-    // @param  service
-    //         The service type for which providers are being sought;
-    //         used to construct error detail strings
-    //
-    // @param  u
-    //         The URL naming the configuration file to be parsed
-    //
-    // @return A (possibly empty) iterator that will yield the provider-class
-    //         names in the given configuration file that are not yet members
-    //         of the returned set
-    //
-    // @throws ServiceConfigurationError
-    //         If an I/O error occurs while reading from the given URL, or
-    //         if a configuration-file format error is detected
-    //
-    private Iterator<String> parse(Class<?> service, URL u)
-        throws ServiceConfigurationError
-    {
-        InputStream in = null;
-        BufferedReader r = null;
-        ArrayList<String> names = new ArrayList<>();
+    /**
+     * Returns the public static "provider" method if found.
+     *
+     * @throws ServiceConfigurationError if there is an error finding the
+     *         provider method or there is more than one public static
+     *         provider method
+     */
+    private Method findStaticProviderMethod(Class<?> clazz) {
+        List<Method> methods = null;
         try {
-            in = u.openStream();
-            r = new BufferedReader(new InputStreamReader(in, "utf-8"));
-            int lc = 1;
-            while ((lc = parseLine(service, u, r, lc, names)) >= 0);
-        } catch (IOException x) {
-            fail(service, "Error reading configuration file", x);
-        } finally {
-            try {
-                if (r != null) r.close();
-                if (in != null) in.close();
-            } catch (IOException y) {
-                fail(service, "Error closing configuration file", y);
+            methods = LANG_ACCESS.getDeclaredPublicMethods(clazz, "provider");
+        } catch (Throwable x) {
+            fail(service, "Unable to get public provider() method", x);
+        }
+        if (methods.isEmpty()) {
+            // does not declare a public provider method
+            return null;
+        }
+
+        // locate the static methods, can be at most one
+        Method result = null;
+        for (Method method : methods) {
+            int mods = method.getModifiers();
+            assert Modifier.isPublic(mods);
+            if (Modifier.isStatic(mods)) {
+                if (result != null) {
+                    fail(service, clazz + " declares more than one"
+                         + " public static provider() method");
+                }
+                result = method;
             }
         }
-        return names.iterator();
+        if (result != null) {
+            Method m = result;
+            PrivilegedAction<Void> pa = () -> {
+                m.setAccessible(true);
+                return null;
+            };
+            AccessController.doPrivileged(pa);
+        }
+        return result;
     }
 
-    // Private inner class implementing fully-lazy provider lookup
-    //
-    private class LazyIterator
-        implements Iterator<S>
-    {
+    /**
+     * Returns the public no-arg constructor of a class.
+     *
+     * @throws ServiceConfigurationError if the class does not have
+     *         public no-arg constructor
+     */
+    private Constructor<?> getConstructor(Class<?> clazz) {
+        PrivilegedExceptionAction<Constructor<?>> pa
+            = new PrivilegedExceptionAction<>() {
+                @Override
+                public Constructor<?> run() throws Exception {
+                    Constructor<?> ctor = clazz.getConstructor();
+                    if (inExplicitModule(clazz))
+                        ctor.setAccessible(true);
+                    return ctor;
+                }
+            };
+        Constructor<?> ctor = null;
+        try {
+            ctor = AccessController.doPrivileged(pa);
+        } catch (Throwable x) {
+            if (x instanceof PrivilegedActionException)
+                x = x.getCause();
+            String cn = clazz.getName();
+            fail(service, cn + " Unable to get public no-arg constructor", x);
+        }
+        return ctor;
+    }
 
-        Class<S> service;
-        ClassLoader loader;
-        Enumeration<URL> configs = null;
-        Iterator<String> pending = null;
-        String nextName = null;
+    /**
+     * A Provider implementation that supports invoking, with reduced
+     * permissions, the static factory to obtain the provider or the
+     * provider's no-arg constructor.
+     */
+    private static class ProviderImpl<S> implements Provider<S> {
+        final Class<S> service;
+        final Class<? extends S> type;
+        final Method factoryMethod;  // factory method or null
+        final Constructor<? extends S> ctor; // public no-args constructor or null
+        final AccessControlContext acc;
 
-        private LazyIterator(Class<S> service, ClassLoader loader) {
+        ProviderImpl(Class<S> service,
+                     Class<? extends S> type,
+                     Method factoryMethod,
+                     AccessControlContext acc) {
             this.service = service;
-            this.loader = loader;
+            this.type = type;
+            this.factoryMethod = factoryMethod;
+            this.ctor = null;
+            this.acc = acc;
         }
 
-        private boolean hasNextService() {
-            if (nextName != null) {
-                return true;
+        ProviderImpl(Class<S> service,
+                     Class<? extends S> type,
+                     Constructor<? extends S> ctor,
+                     AccessControlContext acc) {
+            this.service = service;
+            this.type = type;
+            this.factoryMethod = null;
+            this.ctor = ctor;
+            this.acc = acc;
+        }
+
+        @Override
+        public Class<? extends S> type() {
+            return type;
+        }
+
+        @Override
+        public S get() {
+            if (factoryMethod != null) {
+                return invokeFactoryMethod();
+            } else {
+                return newInstance();
             }
+        }
+
+        /**
+         * Invokes the provider's "provider" method to instantiate a provider.
+         * When running with a security manager then the method runs with
+         * permissions that are restricted by the security context of whatever
+         * created this loader.
+         */
+        private S invokeFactoryMethod() {
+            Object result = null;
+            Throwable exc = null;
+            if (acc == null) {
+                try {
+                    result = factoryMethod.invoke(null);
+                } catch (Throwable x) {
+                    exc = x;
+                }
+            } else {
+                PrivilegedExceptionAction<?> pa = new PrivilegedExceptionAction<>() {
+                    @Override
+                    public Object run() throws Exception {
+                        return factoryMethod.invoke(null);
+                    }
+                };
+                // invoke factory method with permissions restricted by acc
+                try {
+                    result = AccessController.doPrivileged(pa, acc);
+                } catch (Throwable x) {
+                    if (x instanceof PrivilegedActionException)
+                        x = x.getCause();
+                    exc = x;
+                }
+            }
+            if (exc != null) {
+                if (exc instanceof InvocationTargetException)
+                    exc = exc.getCause();
+                fail(service, factoryMethod + " failed", exc);
+            }
+            if (result == null) {
+                fail(service, factoryMethod + " returned null");
+            }
+            @SuppressWarnings("unchecked")
+            S p = (S) result;
+            return p;
+        }
+
+        /**
+         * Invokes Constructor::newInstance to instantiate a provider. When running
+         * with a security manager then the constructor runs with permissions that
+         * are restricted by the security context of whatever created this loader.
+         */
+        private S newInstance() {
+            S p = null;
+            Throwable exc = null;
+            if (acc == null) {
+                try {
+                    p = ctor.newInstance();
+                } catch (Throwable x) {
+                    exc = x;
+                }
+            } else {
+                PrivilegedExceptionAction<S> pa = new PrivilegedExceptionAction<>() {
+                    @Override
+                    public S run() throws Exception {
+                        return ctor.newInstance();
+                    }
+                };
+                // invoke constructor with permissions restricted by acc
+                try {
+                    p = AccessController.doPrivileged(pa, acc);
+                } catch (Throwable x) {
+                    if (x instanceof PrivilegedActionException)
+                        x = x.getCause();
+                    exc = x;
+                }
+            }
+            if (exc != null) {
+                if (exc instanceof InvocationTargetException)
+                    exc = exc.getCause();
+                String cn = ctor.getDeclaringClass().getName();
+                fail(service,
+                     "Provider " + cn + " could not be instantiated", exc);
+            }
+            return p;
+        }
+
+        // For now, equals/hashCode uses the access control context to ensure
+        // that two Providers created with different contexts are not equal
+        // when running with a security manager.
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(service, type, acc);
+        }
+
+        @Override
+        public boolean equals(Object ob) {
+            if (!(ob instanceof ProviderImpl))
+                return false;
+            @SuppressWarnings("unchecked")
+            ProviderImpl<?> that = (ProviderImpl<?>)ob;
+            return this.service == that.service
+                    && this.type == that.type
+                    && Objects.equals(this.acc, that.acc);
+        }
+    }
+
+    /**
+     * Loads a service provider in a module.
+     *
+     * Returns {@code null} if the service provider's module doesn't read
+     * the module with the service type.
+     *
+     * @throws ServiceConfigurationError if the class cannot be loaded or
+     *         isn't the expected sub-type (or doesn't define a provider
+     *         factory method that returns the expected type)
+     */
+    private Provider<S> loadProvider(ServiceProvider provider) {
+        Module module = provider.module();
+        if (!module.canRead(service.getModule())) {
+            // module does not read the module with the service type
+            return null;
+        }
+
+        String cn = provider.providerName();
+        Class<?> clazz = null;
+        if (acc == null) {
+            try {
+                clazz = Class.forName(module, cn);
+            } catch (LinkageError e) {
+                fail(service, "Unable to load " + cn, e);
+            }
+        } else {
+            PrivilegedExceptionAction<Class<?>> pa = () -> Class.forName(module, cn);
+            try {
+                clazz = AccessController.doPrivileged(pa);
+            } catch (Throwable x) {
+                if (x instanceof PrivilegedActionException)
+                    x = x.getCause();
+                fail(service, "Unable to load " + cn, x);
+                return null;
+            }
+        }
+        if (clazz == null) {
+            fail(service, "Provider " + cn + " not found");
+        }
+
+        int mods = clazz.getModifiers();
+        if (!Modifier.isPublic(mods)) {
+            fail(service, clazz + " is not public");
+        }
+
+        // if provider in explicit module then check for static factory method
+        if (inExplicitModule(clazz)) {
+            Method factoryMethod = findStaticProviderMethod(clazz);
+            if (factoryMethod != null) {
+                Class<?> returnType = factoryMethod.getReturnType();
+                if (!service.isAssignableFrom(returnType)) {
+                    fail(service, factoryMethod + " return type not a subtype");
+                }
+
+                @SuppressWarnings("unchecked")
+                Class<? extends S> type = (Class<? extends S>) returnType;
+                return new ProviderImpl<S>(service, type, factoryMethod, acc);
+            }
+        }
+
+        // no factory method so must be a subtype
+        if (!service.isAssignableFrom(clazz)) {
+            fail(service, clazz.getName() + " not a subtype");
+        }
+
+        @SuppressWarnings("unchecked")
+        Class<? extends S> type = (Class<? extends S>) clazz;
+        @SuppressWarnings("unchecked")
+        Constructor<? extends S> ctor = (Constructor<? extends S> ) getConstructor(clazz);
+        return new ProviderImpl<S>(service, type, ctor, acc);
+    }
+
+    /**
+     * Implements lazy service provider lookup of service providers that
+     * are provided by modules in a module layer (or parent layers)
+     */
+    private final class LayerLookupIterator<T>
+        implements Iterator<Provider<T>>
+    {
+        Deque<ModuleLayer> stack = new ArrayDeque<>();
+        Set<ModuleLayer> visited = new HashSet<>();
+        Iterator<ServiceProvider> iterator;
+
+        Provider<T> nextProvider;
+        ServiceConfigurationError nextError;
+
+        LayerLookupIterator() {
+            visited.add(layer);
+            stack.push(layer);
+        }
+
+        private Iterator<ServiceProvider> providers(ModuleLayer layer) {
+            ServicesCatalog catalog = LANG_ACCESS.getServicesCatalog(layer);
+            return catalog.findServices(serviceName).iterator();
+        }
+
+        @Override
+        public boolean hasNext() {
+            while (nextProvider == null && nextError == null) {
+                // get next provider to load
+                while (iterator == null || !iterator.hasNext()) {
+                    // next layer (DFS order)
+                    if (stack.isEmpty())
+                        return false;
+
+                    ModuleLayer layer = stack.pop();
+                    List<ModuleLayer> parents = layer.parents();
+                    for (int i = parents.size() - 1; i >= 0; i--) {
+                        ModuleLayer parent = parents.get(i);
+                        if (visited.add(parent)) {
+                            stack.push(parent);
+                        }
+                    }
+                    iterator = providers(layer);
+                }
+
+                // attempt to load provider
+                ServiceProvider provider = iterator.next();
+                try {
+                    @SuppressWarnings("unchecked")
+                    Provider<T> next = (Provider<T>) loadProvider(provider);
+                    nextProvider = next;
+                } catch (ServiceConfigurationError e) {
+                    nextError = e;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public Provider<T> next() {
+            if (!hasNext())
+                throw new NoSuchElementException();
+
+            Provider<T> provider = nextProvider;
+            if (provider != null) {
+                nextProvider = null;
+                return provider;
+            } else {
+                ServiceConfigurationError e = nextError;
+                assert e != null;
+                nextError = null;
+                throw e;
+            }
+        }
+    }
+
+    /**
+     * Implements lazy service provider lookup of service providers that
+     * are provided by modules defined to a class loader or to modules in
+     * layers with a module defined to the class loader.
+     */
+    private final class ModuleServicesLookupIterator<T>
+        implements Iterator<Provider<T>>
+    {
+        ClassLoader currentLoader;
+        Iterator<ServiceProvider> iterator;
+
+        Provider<T> nextProvider;
+        ServiceConfigurationError nextError;
+
+        ModuleServicesLookupIterator() {
+            this.currentLoader = loader;
+            this.iterator = iteratorFor(loader);
+        }
+
+        /**
+         * Returns iterator to iterate over the implementations of {@code
+         * service} in the given layer.
+         */
+        private List<ServiceProvider> providers(ModuleLayer layer) {
+            ServicesCatalog catalog = LANG_ACCESS.getServicesCatalog(layer);
+            return catalog.findServices(serviceName);
+        }
+
+        /**
+         * Returns the class loader that a module is defined to
+         */
+        private ClassLoader loaderFor(Module module) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm == null) {
+                return module.getClassLoader();
+            } else {
+                PrivilegedAction<ClassLoader> pa = module::getClassLoader;
+                return AccessController.doPrivileged(pa);
+            }
+        }
+
+        /**
+         * Returns an iterator to iterate over the implementations of {@code
+         * service} in modules defined to the given class loader or in custom
+         * layers with a module defined to this class loader.
+         */
+        private Iterator<ServiceProvider> iteratorFor(ClassLoader loader) {
+            // modules defined to the class loader
+            ServicesCatalog catalog;
+            if (loader == null) {
+                catalog = BootLoader.getServicesCatalog();
+            } else {
+                catalog = ServicesCatalog.getServicesCatalogOrNull(loader);
+            }
+            List<ServiceProvider> providers;
+            if (catalog == null) {
+                providers = List.of();
+            } else {
+                providers = catalog.findServices(serviceName);
+            }
+
+            // modules in layers that define modules to the class loader
+            ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
+            if (loader == null || loader == platformClassLoader) {
+                return providers.iterator();
+            } else {
+                List<ServiceProvider> allProviders = new ArrayList<>(providers);
+                Iterator<ModuleLayer> iterator = LANG_ACCESS.layers(loader).iterator();
+                while (iterator.hasNext()) {
+                    ModuleLayer layer = iterator.next();
+                    for (ServiceProvider sp : providers(layer)) {
+                        ClassLoader l = loaderFor(sp.module());
+                        if (l != null && l != platformClassLoader) {
+                            allProviders.add(sp);
+                        }
+                    }
+                }
+                return allProviders.iterator();
+            }
+        }
+
+        @Override
+        public boolean hasNext() {
+            while (nextProvider == null && nextError == null) {
+                // get next provider to load
+                while (!iterator.hasNext()) {
+                    if (currentLoader == null) {
+                        return false;
+                    } else {
+                        currentLoader = currentLoader.getParent();
+                        iterator = iteratorFor(currentLoader);
+                    }
+                }
+
+                // attempt to load provider
+                ServiceProvider provider = iterator.next();
+                try {
+                    @SuppressWarnings("unchecked")
+                    Provider<T> next = (Provider<T>) loadProvider(provider);
+                    nextProvider = next;
+                } catch (ServiceConfigurationError e) {
+                    nextError = e;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public Provider<T> next() {
+            if (!hasNext())
+                throw new NoSuchElementException();
+
+            Provider<T> provider = nextProvider;
+            if (provider != null) {
+                nextProvider = null;
+                return provider;
+            } else {
+                ServiceConfigurationError e = nextError;
+                assert e != null;
+                nextError = null;
+                throw e;
+            }
+        }
+    }
+
+    /**
+     * Implements lazy service provider lookup where the service providers are
+     * configured via service configuration files. Service providers in named
+     * modules are silently ignored by this lookup iterator.
+     */
+    private final class LazyClassPathLookupIterator<T>
+        implements Iterator<Provider<T>>
+    {
+        static final String PREFIX = "META-INF/services/";
+
+        Set<String> providerNames = new HashSet<>();  // to avoid duplicates
+        Enumeration<URL> configs;
+        Iterator<String> pending;
+
+        Provider<T> nextProvider;
+        ServiceConfigurationError nextError;
+
+        LazyClassPathLookupIterator() { }
+
+        /**
+         * Parse a single line from the given configuration file, adding the
+         * name on the line to set of names if not already seen.
+         */
+        private int parseLine(URL u, BufferedReader r, int lc, Set<String> names)
+            throws IOException
+        {
+            String ln = r.readLine();
+            if (ln == null) {
+                return -1;
+            }
+            int ci = ln.indexOf('#');
+            if (ci >= 0) ln = ln.substring(0, ci);
+            ln = ln.trim();
+            int n = ln.length();
+            if (n != 0) {
+                if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
+                    fail(service, u, lc, "Illegal configuration-file syntax");
+                int cp = ln.codePointAt(0);
+                if (!Character.isJavaIdentifierStart(cp))
+                    fail(service, u, lc, "Illegal provider-class name: " + ln);
+                int start = Character.charCount(cp);
+                for (int i = start; i < n; i += Character.charCount(cp)) {
+                    cp = ln.codePointAt(i);
+                    if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
+                        fail(service, u, lc, "Illegal provider-class name: " + ln);
+                }
+                if (providerNames.add(ln)) {
+                    names.add(ln);
+                }
+            }
+            return lc + 1;
+        }
+
+        /**
+         * Parse the content of the given URL as a provider-configuration file.
+         */
+        private Iterator<String> parse(URL u) {
+            Set<String> names = new LinkedHashSet<>(); // preserve insertion order
+            try {
+                URLConnection uc = u.openConnection();
+                uc.setUseCaches(false);
+                try (InputStream in = uc.getInputStream();
+                     BufferedReader r
+                         = new BufferedReader(new InputStreamReader(in, "utf-8")))
+                {
+                    int lc = 1;
+                    while ((lc = parseLine(u, r, lc, names)) >= 0);
+                }
+            } catch (IOException x) {
+                fail(service, "Error accessing configuration file", x);
+            }
+            return names.iterator();
+        }
+
+        /**
+         * Loads and returns the next provider class.
+         */
+        private Class<?> nextProviderClass() {
             if (configs == null) {
                 try {
                     String fullName = PREFIX + service.getName();
-                    if (loader == null)
+                    if (loader == null) {
                         configs = ClassLoader.getSystemResources(fullName);
-                    else
+                    } else if (loader == ClassLoaders.platformClassLoader()) {
+                        // The platform classloader doesn't have a class path,
+                        // but the boot loader might.
+                        if (BootLoader.hasClassPath()) {
+                            configs = BootLoader.findResources(fullName);
+                        } else {
+                            configs = Collections.emptyEnumeration();
+                        }
+                    } else {
                         configs = loader.getResources(fullName);
+                    }
                 } catch (IOException x) {
                     fail(service, "Error locating configuration files", x);
                 }
             }
             while ((pending == null) || !pending.hasNext()) {
                 if (!configs.hasMoreElements()) {
-                    return false;
+                    return null;
                 }
-                pending = parse(service, configs.nextElement());
+                pending = parse(configs.nextElement());
             }
-            nextName = pending.next();
+            String cn = pending.next();
+            try {
+                return Class.forName(cn, false, loader);
+            } catch (ClassNotFoundException x) {
+                fail(service, "Provider " + cn + " not found");
+                return null;
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        private boolean hasNextService() {
+            while (nextProvider == null && nextError == null) {
+                try {
+                    Class<?> clazz = nextProviderClass();
+                    if (clazz == null)
+                        return false;
+
+                    if (clazz.getModule().isNamed()) {
+                        // ignore class if in named module
+                        continue;
+                    }
+
+                    if (service.isAssignableFrom(clazz)) {
+                        Class<? extends S> type = (Class<? extends S>) clazz;
+                        Constructor<? extends S> ctor
+                            = (Constructor<? extends S>)getConstructor(clazz);
+                        ProviderImpl<S> p = new ProviderImpl<S>(service, type, ctor, acc);
+                        nextProvider = (ProviderImpl<T>) p;
+                    } else {
+                        fail(service, clazz.getName() + " not a subtype");
+                    }
+                } catch (ServiceConfigurationError e) {
+                    nextError = e;
+                }
+            }
             return true;
         }
 
-        private S nextService() {
+        private Provider<T> nextService() {
             if (!hasNextService())
                 throw new NoSuchElementException();
-            String cn = nextName;
-            nextName = null;
-            Class<?> c = null;
-            try {
-                c = Class.forName(cn, false, loader);
-            } catch (ClassNotFoundException x) {
-                fail(service,
-                     "Provider " + cn + " not found");
+
+            Provider<T> provider = nextProvider;
+            if (provider != null) {
+                nextProvider = null;
+                return provider;
+            } else {
+                ServiceConfigurationError e = nextError;
+                assert e != null;
+                nextError = null;
+                throw e;
             }
-            if (!service.isAssignableFrom(c)) {
-                fail(service,
-                     "Provider " + cn  + " not a subtype");
-            }
-            try {
-                S p = service.cast(c.newInstance());
-                providers.put(cn, p);
-                return p;
-            } catch (Throwable x) {
-                fail(service,
-                     "Provider " + cn + " could not be instantiated",
-                     x);
-            }
-            throw new Error();          // This cannot happen
         }
 
+        @Override
         public boolean hasNext() {
             if (acc == null) {
                 return hasNextService();
             } else {
-                PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
+                PrivilegedAction<Boolean> action = new PrivilegedAction<>() {
                     public Boolean run() { return hasNextService(); }
                 };
                 return AccessController.doPrivileged(action, acc);
             }
         }
 
-        public S next() {
+        @Override
+        public Provider<T> next() {
             if (acc == null) {
                 return nextService();
             } else {
-                PrivilegedAction<S> action = new PrivilegedAction<S>() {
-                    public S run() { return nextService(); }
+                PrivilegedAction<Provider<T>> action = new PrivilegedAction<>() {
+                    public Provider<T> run() { return nextService(); }
                 };
                 return AccessController.doPrivileged(action, acc);
             }
         }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
     }
 
     /**
-     * Lazily loads the available providers of this loader's service.
+     * Returns a new lookup iterator.
+     */
+    private Iterator<Provider<S>> newLookupIterator() {
+        assert layer == null || loader == null;
+        if (layer != null) {
+            return new LayerLookupIterator<>();
+        } else {
+            Iterator<Provider<S>> first = new ModuleServicesLookupIterator<>();
+            Iterator<Provider<S>> second = new LazyClassPathLookupIterator<>();
+            return new Iterator<Provider<S>>() {
+                @Override
+                public boolean hasNext() {
+                    return (first.hasNext() || second.hasNext());
+                }
+                @Override
+                public Provider<S> next() {
+                    if (first.hasNext()) {
+                        return first.next();
+                    } else if (second.hasNext()) {
+                        return second.next();
+                    } else {
+                        throw new NoSuchElementException();
+                    }
+                }
+            };
+        }
+    }
+
+    /**
+     * Returns an iterator to lazily load and instantiate the available
+     * providers of this loader's service.
      *
-     * <p> The iterator returned by this method first yields all of the
-     * elements of the provider cache, in instantiation order.  It then lazily
-     * loads and instantiates any remaining providers, adding each one to the
-     * cache in turn.
-     *
-     * <p> To achieve laziness the actual work of parsing the available
-     * provider-configuration files and instantiating providers must be done by
-     * the iterator itself.  Its {@link java.util.Iterator#hasNext hasNext} and
-     * {@link java.util.Iterator#next next} methods can therefore throw a
-     * {@link ServiceConfigurationError} if a provider-configuration file
-     * violates the specified format, or if it names a provider class that
-     * cannot be found and instantiated, or if the result of instantiating the
-     * class is not assignable to the service type, or if any other kind of
-     * exception or error is thrown as the next provider is located and
-     * instantiated.  To write robust code it is only necessary to catch {@link
-     * ServiceConfigurationError} when using a service iterator.
-     *
-     * <p> If such an error is thrown then subsequent invocations of the
+     * <p> To achieve laziness the actual work of locating and instantiating
+     * providers is done by the iterator itself. Its {@link Iterator#hasNext
+     * hasNext} and {@link Iterator#next next} methods can therefore throw a
+     * {@link ServiceConfigurationError} for any of the reasons specified in
+     * the <a href="#errors">Errors</a> section above. To write robust code it
+     * is only necessary to catch {@code ServiceConfigurationError} when using
+     * the iterator. If an error is thrown then subsequent invocations of the
      * iterator will make a best effort to locate and instantiate the next
      * available provider, but in general such recovery cannot be guaranteed.
      *
-     * <blockquote style="font-size: smaller; line-height: 1.2"><span
-     * style="padding-right: 1em; font-weight: bold">Design Note</span>
-     * Throwing an error in these cases may seem extreme.  The rationale for
-     * this behavior is that a malformed provider-configuration file, like a
-     * malformed class file, indicates a serious problem with the way the Java
-     * virtual machine is configured or is being used.  As such it is
-     * preferable to throw an error rather than try to recover or, even worse,
-     * fail silently.</blockquote>
+     * <p> Caching: The iterator returned by this method first yields all of
+     * the elements of the provider cache, in the order that they were loaded.
+     * It then lazily loads and instantiates any remaining service providers,
+     * adding each one to the cache in turn. If this loader's provider caches are
+     * cleared by invoking the {@link #reload() reload} method then existing
+     * iterators for this service loader should be discarded.
+     * The {@code  hasNext} and {@code next} methods of the iterator throw {@link
+     * java.util.ConcurrentModificationException ConcurrentModificationException}
+     * if used after the provider cache has been cleared.
      *
      * <p> The iterator returned by this method does not support removal.
      * Invoking its {@link java.util.Iterator#remove() remove} method will
      * cause an {@link UnsupportedOperationException} to be thrown.
      *
-     * @implNote When adding providers to the cache, the {@link #iterator
-     * Iterator} processes resources in the order that the {@link
-     * java.lang.ClassLoader#getResources(java.lang.String)
-     * ClassLoader.getResources(String)} method finds the service configuration
-     * files.
+     * @apiNote Throwing an error in these cases may seem extreme.  The rationale
+     * for this behavior is that a malformed provider-configuration file, like a
+     * malformed class file, indicates a serious problem with the way the Java
+     * virtual machine is configured or is being used.  As such it is preferable
+     * to throw an error rather than try to recover or, even worse, fail silently.
      *
      * @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) {
+            lookupIterator1 = newLookupIterator();
+        }
+
         return new Iterator<S>() {
 
-            Iterator<Map.Entry<String,S>> knownProviders
-                = providers.entrySet().iterator();
+            // record reload count
+            final int expectedReloadCount = ServiceLoader.this.reloadCount;
 
+            // index into the cached providers list
+            int index;
+
+            /**
+             * Throws ConcurrentModificationException if the list of cached
+             * providers has been cleared by reload.
+             */
+            private void checkReloadCount() {
+                if (ServiceLoader.this.reloadCount != expectedReloadCount)
+                    throw new ConcurrentModificationException();
+            }
+
+            @Override
             public boolean hasNext() {
-                if (knownProviders.hasNext())
+                checkReloadCount();
+                if (index < instantiatedProviders.size())
                     return true;
-                return lookupIterator.hasNext();
+                return lookupIterator1.hasNext();
             }
 
+            @Override
             public S next() {
-                if (knownProviders.hasNext())
-                    return knownProviders.next().getValue();
-                return lookupIterator.next();
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
+                checkReloadCount();
+                S next;
+                if (index < instantiatedProviders.size()) {
+                    next = instantiatedProviders.get(index);
+                } else {
+                    next = lookupIterator1.next().get();
+                    instantiatedProviders.add(next);
+                }
+                index++;
+                return next;
             }
 
         };
     }
 
     /**
-     * Creates a new service loader for the given service type and class
-     * loader.
+     * Returns a stream to lazily load available providers of this loader's
+     * service. The stream elements are of type {@link Provider Provider}, the
+     * {@code Provider}'s {@link Provider#get() get} method must be invoked to
+     * get or instantiate the provider.
+     *
+     * <p> To achieve laziness the actual work of locating providers is done
+     * when processing the stream. If a service provider cannot be loaded for any
+     * of the reasons specified in the <a href="#errors">Errors</a> section
+     * above then {@link ServiceConfigurationError} is thrown by whatever method
+     * caused the service provider to be loaded. </p>
+     *
+     * <p> Caching: When processing the stream then providers that were previously
+     * loaded by stream operations are processed first, in load order. It then
+     * lazily loads any remaining service providers. 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. The returned
+     * stream's source {@link Spliterator 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 {@code CodecFactory} objects, the second example is the same
+     * except that it sorts the providers by provider class name (and so locate
+     * all providers).
+     * <pre>{@code
+     *    Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
+     *            .stream()
+     *            .map(Provider::get);
+     *
+     *    Stream<CodecFactory> providers = ServiceLoader.load(CodecFactory.class)
+     *            .stream()
+     *            .sorted(Comparator.comparing(p -> p.type().getName()))
+     *            .map(Provider::get);
+     * }</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();
+        }
+
+        // create lookup iterator if needed
+        if (lookupIterator2 == null) {
+            lookupIterator2 = newLookupIterator();
+        }
+
+        // use lookup iterator and cached providers as source
+        Spliterator<Provider<S>> s = new ProviderSpliterator<>(lookupIterator2);
+        return StreamSupport.stream(s, false);
+    }
+
+    private class ProviderSpliterator<T> implements Spliterator<Provider<T>> {
+        final int expectedReloadCount = ServiceLoader.this.reloadCount;
+        final Iterator<Provider<T>> iterator;
+        int index;
+
+        ProviderSpliterator(Iterator<Provider<T>> iterator) {
+            this.iterator = iterator;
+        }
+
+        @Override
+        public Spliterator<Provider<T>> trySplit() {
+            return null;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public boolean tryAdvance(Consumer<? super Provider<T>> action) {
+            if (ServiceLoader.this.reloadCount != expectedReloadCount)
+                throw new ConcurrentModificationException();
+            Provider<T> next = null;
+            if (index < loadedProviders.size()) {
+                next = (Provider<T>) loadedProviders.get(index++);
+            } else if (iterator.hasNext()) {
+                next = iterator.next();
+                loadedProviders.add((Provider<S>)next);
+                index++;
+            } else {
+                loadedAllProviders = true;
+            }
+            if (next != null) {
+                action.accept(next);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int characteristics() {
+            // not IMMUTABLE as structural interference possible
+            // not NOTNULL so that the characteristics are a subset of the
+            // characteristics when all Providers have been located.
+            return Spliterator.ORDERED;
+        }
+
+        @Override
+        public long estimateSize() {
+            return Long.MAX_VALUE;
+        }
+    }
+
+    /**
+     * Creates a new service loader for the given service type, class
+     * loader, and caller.
      *
      * @param  <S> the class of the service type
      *
      * @param  service
      *         The interface or abstract class representing the service
      *
      * @param  loader
      *         The class loader to be used to load provider-configuration files
-     *         and provider classes, or <tt>null</tt> if the system class
+     *         and provider classes, or {@code null} if the system class
+     *         loader (or, failing that, the bootstrap class loader) is to be
+     *         used
+     *
+     * @param  callerModule
+     *         The caller's module for which a new service loader is created
+     *
+     * @return A new service loader
+     */
+    static <S> ServiceLoader<S> load(Class<S> service,
+                                     ClassLoader loader,
+                                     Module callerModule)
+    {
+        return new ServiceLoader<>(callerModule, service, loader);
+    }
+
+    /**
+     * Creates a new service loader for the given service. The service loader
+     * uses the given class loader as the starting point to locate service
+     * providers for the service. The service loader's {@link #iterator()
+     * iterator} and {@link #stream() stream} locate providers in both named
+     * and unnamed modules, as follows:
+     *
+     * <ul>
+     *   <li> <p> Step 1: Locate providers in named modules. </p>
+     *
+     *   <p> Service providers are located in all named modules of the class
+     *   loader or to any class loader reachable via parent delegation. </p>
+     *
+     *   <p> In addition, if the class loader is not the bootstrap or {@linkplain
+     *   ClassLoader#getPlatformClassLoader() platform class loader}, then service
+     *   providers may be located in the named modules of other class loaders.
+     *   Specifically, if the class loader, or any class loader reachable via
+     *   parent delegation, has a module in a {@linkplain ModuleLayer module
+     *   layer}, then service providers in all modules in the module layer are
+     *   located.  </p>
+     *
+     *   <p> For example, suppose there is a module layer where each module is
+     *   in its own class loader (see {@link ModuleLayer#defineModulesWithManyLoaders
+     *   defineModulesWithManyLoaders}). If this {@code ServiceLoader.load} method
+     *   is invoked to locate providers using any of the class loaders created for
+     *   the module layer, then it will locate all of the providers in the module
+     *   layer, irrespective of their defining class loader. </p>
+     *
+     *   <p> Ordering: The service loader will first locate any service providers
+     *   in modules defined to the class loader, then its parent class loader,
+     *   its parent parent, and so on to the bootstrap class loader. If a class
+     *   loader has modules in a module layer then all providers in that module
+     *   layer are located (irrespective of their class loader) before the
+     *   providers in the parent class loader are located. The ordering of
+     *   modules in same class loader, or the ordering of modules in a module
+     *   layer, is not defined. </p>
+     *
+     *   <p> If a module declares more than one provider then the providers
+     *   are located in the order that its module descriptor {@linkplain
+     *   java.lang.module.ModuleDescriptor.Provides#providers() lists the
+     *   providers}. Providers added dynamically by instrumentation agents (see
+     *   {@link java.lang.instrument.Instrumentation#redefineModule redefineModule})
+     *   are always located after providers declared by the module. </p> </li>
+     *
+     *   <li> <p> Step 2: Locate providers in unnamed modules. </p>
+     *
+     *   <p> Service providers in unnamed modules are located if their class names
+     *   are listed in provider-configuration files located by the class loader's
+     *   {@link ClassLoader#getResources(String) getResources} method. </p>
+     *
+     *   <p> The ordering is based on the order that the class loader's {@code
+     *   getResources} method finds the service configuration files and within
+     *   that, the order that the class names are listed in the file. </p>
+     *
+     *   <p> In a provider-configuration file, any mention of a service provider
+     *   that is deployed in a named module is ignored. This is to avoid
+     *   duplicates that would otherwise arise when a named module has both a
+     *   <i>provides</i> directive and a provider-configuration file that mention
+     *   the same service provider. </p>
+     *
+     *   <p> The provider class must be visible to the class loader. </p> </li>
+     *
+     * </ul>
+     *
+     * @apiNote If the class path of the class loader includes remote network
+     * URLs then those URLs may be dereferenced in the process of searching for
+     * provider-configuration files.
+     *
+     * <p> This activity is normal, although it may cause puzzling entries to be
+     * created in web-server logs.  If a web server is not configured correctly,
+     * however, then this activity may cause the provider-loading algorithm to fail
+     * spuriously.
+     *
+     * <p> A web server should return an HTTP 404 (Not Found) response when a
+     * requested resource does not exist.  Sometimes, however, web servers are
+     * erroneously configured to return an HTTP 200 (OK) response along with a
+     * helpful HTML error page in such cases.  This will cause a {@link
+     * ServiceConfigurationError} to be thrown when this class attempts to parse
+     * the HTML page as a provider-configuration file.  The best solution to this
+     * problem is to fix the misconfigured web server to return the correct
+     * response code (HTTP 404) along with the HTML error page.
+     *
+     * @param  <S> the class of the service type
+     *
+     * @param  service
+     *         The interface or abstract class representing the service
+     *
+     * @param  loader
+     *         The class loader to be used to load provider-configuration files
+     *         and provider classes, or {@code null} if the system class
      *         loader (or, failing that, the bootstrap class loader) is to be
      *         used
      *
      * @return A new service loader
+     *
+     * @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)
     {
-        return new ServiceLoader<>(service, loader);
+        return new ServiceLoader<>(Reflection.getCallerClass(), service, loader);
     }
 
     /**
      * Creates a new service loader for the given service type, using the
      * current thread's {@linkplain java.lang.Thread#getContextClassLoader
      * context class loader}.
      *
      * <p> An invocation of this convenience method of the form
-     *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>)</pre></blockquote>
+     * <pre>{@code
+     *     ServiceLoader.load(service)
+     * }</pre>
      *
      * is equivalent to
      *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>,
-     *                    Thread.currentThread().getContextClassLoader())</pre></blockquote>
+     * <pre>{@code
+     *     ServiceLoader.load(service, Thread.currentThread().getContextClassLoader())
+     * }</pre>
+     *
+     * @apiNote Service loader objects obtained with this method should not be
+     * cached VM-wide. For example, different applications in the same VM may
+     * have different thread context class loaders. A lookup by one application
+     * may locate a service provider that is only visible via its thread
+     * context class loader and so is not suitable to be located by the other
+     * application. Memory leaks can also arise. A thread local may be suited
+     * to some applications.
      *
      * @param  <S> the class of the service type
      *
      * @param  service
      *         The interface or abstract class representing the service
      *
      * @return A new service loader
+     *
+     * @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 ServiceLoader.load(service, cl);
+        return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
     }
 
     /**
      * Creates a new service loader for the given service type, using the
-     * extension class loader.
+     * {@linkplain ClassLoader#getPlatformClassLoader() platform class loader}.
      *
-     * <p> This convenience method simply locates the extension class loader,
-     * call it <tt><i>extClassLoader</i></tt>, and then returns
+     * <p> This convenience method is equivalent to: </p>
      *
-     * <blockquote><pre>
-     * ServiceLoader.load(<i>service</i>, <i>extClassLoader</i>)</pre></blockquote>
-     *
-     * <p> If the extension class loader cannot be found then the system class
-     * loader is used; if there is no system class loader then the bootstrap
-     * class loader is used.
+     * <pre>{@code
+     *     ServiceLoader.load(service, ClassLoader.getPlatformClassLoader())
+     * }</pre>
      *
      * <p> This method is intended for use when only installed providers are
      * desired.  The resulting service will only find and load providers that
      * have been installed into the current Java virtual machine; providers on
-     * the application's class path will be ignored.
+     * the application's module path or class path will be ignored.
      *
      * @param  <S> the class of the service type
      *
      * @param  service
      *         The interface or abstract class representing the service
      *
      * @return A new service loader
+     *
+     * @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.getSystemClassLoader();
-        ClassLoader prev = null;
-        while (cl != null) {
-            prev = cl;
-            cl = cl.getParent();
+        ClassLoader cl = ClassLoader.getPlatformClassLoader();
+        return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
+    }
+
+    /**
+     * Creates a new service loader for the given service type to load service
+     * providers from modules in the given module layer and its ancestors. It
+     * does not locate providers in unnamed modules. The ordering that the service
+     * loader's {@link #iterator() iterator} and {@link #stream() stream} locate
+     * providers and yield elements is as follows:
+     *
+     * <ul>
+     *   <li><p> Providers are located in a module layer before locating providers
+     *   in parent layers. Traversal of parent layers is depth-first with each
+     *   layer visited at most once. For example, suppose L0 is the boot layer, L1
+     *   and L2 are modules layers with L0 as their parent. Now suppose that L3 is
+     *   created with L1 and L2 as the parents (in that order). Using a service
+     *   loader to locate providers with L3 as the context will locate providers
+     *   in the following order: L3, L1, L0, L2. </p></li>
+     *
+     *   <li><p> If a module declares more than one provider then the providers
+     *   are located in the order that its module descriptor
+     *   {@linkplain java.lang.module.ModuleDescriptor.Provides#providers()
+     *   lists the providers}. Providers added dynamically by instrumentation
+     *   agents are always located after providers declared by the module. </p></li>
+     *
+     *   <li><p> The ordering of modules in a module layer is not defined. </p></li>
+     * </ul>
+     *
+     * @apiNote Unlike the other load methods defined here, the service type
+     * is the second parameter. The reason for this is to avoid source
+     * compatibility issues for code that uses {@code load(S, null)}.
+     *
+     * @param  <S> the class of the service type
+     *
+     * @param  layer
+     *         The module layer
+     *
+     * @param  service
+     *         The interface or abstract class representing the service
+     *
+     * @return A new service loader
+     *
+     * @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}
+     *
+     * @since 9
+     * @spec JPMS
+     */
+    @CallerSensitive
+    public static <S> ServiceLoader<S> load(ModuleLayer layer, Class<S> service) {
+        return new ServiceLoader<>(Reflection.getCallerClass(), layer, service);
+    }
+
+    /**
+     * Load the first available service provider of this loader's service. This
+     * convenience method is equivalent to invoking the {@link #iterator()
+     * iterator()} method and obtaining the first element. It therefore
+     * returns the first element from the provider cache if possible, it
+     * otherwise attempts to load and instantiate the first provider.
+     *
+     * <p> The following example loads the first available service provider. If
+     * no service providers are located then it uses a default implementation.
+     * <pre>{@code
+     *    CodecFactory factory = ServiceLoader.load(CodecFactory.class)
+     *                                        .findFirst()
+     *                                        .orElse(DEFAULT_CODECSET_FACTORY);
+     * }</pre>
+     * @return The first service provider or empty {@code Optional} if no
+     *         service providers are located
+     *
+     * @throws ServiceConfigurationError
+     *         If a provider class cannot be loaded for any of the reasons
+     *         specified in the <a href="#errors">Errors</a> section above.
+     *
+     * @since 9
+     * @spec JPMS
+     */
+    public Optional<S> findFirst() {
+        Iterator<S> iterator = iterator();
+        if (iterator.hasNext()) {
+            return Optional.of(iterator.next());
+        } else {
+            return Optional.empty();
         }
-        return ServiceLoader.load(service, prev);
+    }
+
+    /**
+     * Clear this loader's provider cache so that all providers will be
+     * reloaded.
+     *
+     * <p> After invoking this method, subsequent invocations of the {@link
+     * #iterator() iterator} or {@link #stream() stream} methods will lazily
+     * locate providers (and instantiate in the case of {@code iterator})
+     * from scratch, just as is done by a newly-created service loader.
+     *
+     * <p> This method is intended for use in situations in which new service
+     * providers can be installed into a running Java virtual machine.
+     */
+    public void reload() {
+        lookupIterator1 = null;
+        instantiatedProviders.clear();
+
+        lookupIterator2 = null;
+        loadedProviders.clear();
+        loadedAllProviders = false;
+
+        // increment count to allow CME be thrown
+        reloadCount++;
     }
 
     /**
      * Returns a string describing this service.
      *
      * @return  A descriptive string
      */
     public String toString() {
         return "java.util.ServiceLoader[" + service.getName() + "]";
     }
 
 }