/*
 * Copyright (c) 2005, 2025, 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.net.URLConnection;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import sun.nio.cs.UTF_8;

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 facility to load implementations of a service.
 *
 * <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.
 *
 * <h2> Obtaining a service loader </h2>
 *
 * <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> 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> 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>
 *
 * <h2> Designing services </h2>
 *
 * <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>
 *
 * <h2> <a id="developing-service-providers">Developing service providers</a> </h2>
 *
 * <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.
 *
 * <h2> Deploying service providers as modules </h2>
 *
 * <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 directive:
 * <pre>{@code
 *     provides com.example.CodecFactory with com.example.impl.StandardCodecs,
 *              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.
 *
 * <h2> Deploying service providers on the class path </h2>
 *
 * 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 U+0023} <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.
 *
 * <h2> Timing of provider discovery </h2>
 *
 * <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. 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.
 *
 * <h2> <a id="errors">Errors</a> </h2>
 *
 * <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>
 *
 * <h2> Concurrency </h2>
 *
 * <p> Instances of this class are not safe for use by multiple concurrent
 * threads.
 *
 * <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.
 *
 * @param  <S>
 *         The type of the service to be loaded by this loader
 *
 * @author Mark Reinhold
 * @since 1.6
 */

public final class ServiceLoader<S>
    implements Iterable<S>
{
    // The class or interface representing the service being loaded
    private final Class<S> service;

    // 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 lazy-lookup iterator for iterator operations
    private Iterator<Provider<S>> lookupIterator1;
    private final List<S> instantiatedProviders = new ArrayList<>();

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

    // Incremented when reload is called
    private int reloadCount;

    private static final JavaLangAccess LANG_ACCESS = SharedSecrets.getJavaLangAccess();

    /**
     * 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
     */
    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;
    }

    /**
     * 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;
    }

    /**
     * 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;
    }

    /**
     * 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);
    }

    /**
     * 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();
    }

    /**
     * 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 {
            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;
            }
        }
        if (result != null) {
            result.setAccessible(true);
        }
        return result;
    }

    /**
     * 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) {
        Constructor<?> ctor = null;
        try {
            ctor = clazz.getConstructor();
        } catch (NoSuchMethodException ex) {
            String cn = clazz.getName();
            fail(service, cn + " Unable to get public no-arg constructor", ex);
        }
        if (inExplicitModule(clazz))
            ctor.setAccessible(true);
        return ctor;
    }

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

        ProviderImpl(Class<S> service,
                     Class<? extends S> type,
                     Method factoryMethod) {
            this.service = service;
            this.type = type;
            this.factoryMethod = factoryMethod;
            this.ctor = null;
        }

        ProviderImpl(Class<S> service,
                     Class<? extends S> type,
                     Constructor<? extends S> ctor) {
            this.service = service;
            this.type = type;
            this.factoryMethod = null;
            this.ctor = ctor;
        }

        @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;
            try {
                result = factoryMethod.invoke(null);
            } catch (Throwable ex) {
                if (ex instanceof InvocationTargetException)
                    ex = ex.getCause();
                fail(service, factoryMethod + " failed", ex);
            }
            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;
            try {
                p = ctor.newInstance();
            } catch (Throwable ex) {
                if (ex instanceof InvocationTargetException)
                    ex = ex.getCause();
                String cn = ctor.getDeclaringClass().getName();
                fail(service,
                     "Provider " + cn + " could not be instantiated", ex);
            }
            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);
        }

        @Override
        public boolean equals(Object ob) {
            return ob instanceof ProviderImpl<?> that
                    && this.service == that.service
                    && this.type == that.type;
        }
    }

    /**
     * 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;
        try {
            clazz = Class.forName(module, cn);
        } catch (LinkageError e) {
            fail(service, "Unable to load " + cn, e);
        }
        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);
            }
        }

        // 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);
    }

    /**
     * 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 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 = sp.module().getClassLoader();
                        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.INSTANCE)))
                {
                    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) {
                        configs = ClassLoader.getSystemResources(fullName);
                    } 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 null;
                }
                pending = parse(configs.nextElement());
            }
            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);
                        nextProvider = (ProviderImpl<T>) p;
                    } else {
                        fail(service, clazz.getName() + " not a subtype");
                    }
                } catch (ServiceConfigurationError e) {
                    nextError = e;
                }
            }
            return true;
        }

        private Provider<T> nextService() {
            if (!hasNextService())
                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;
            }
        }

        @Override
        public boolean hasNext() {
            return hasNextService();
        }

        @Override
        public Provider<T> next() {
            return nextService();
        }
    }

    /**
     * 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> 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.
     *
     * <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.
     *
     * @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
     */
    public Iterator<S> iterator() {

        // create lookup iterator if needed
        if (lookupIterator1 == null) {
            lookupIterator1 = newLookupIterator();
        }

        return new Iterator<S>() {

            // 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() {
                checkReloadCount();
                if (index < instantiatedProviders.size())
                    return true;
                return lookupIterator1.hasNext();
            }

            @Override
            public S next() {
                checkReloadCount();
                S next;
                if (index < instantiatedProviders.size()) {
                    next = instantiatedProviders.get(index);
                } else {
                    next = lookupIterator1.next().get();
                    instantiatedProviders.add(next);
                }
                index++;
                return next;
            }

        };
    }

    /**
     * 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
     */
    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 {@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.instrument/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}
     */
    @CallerSensitive
    @SuppressWarnings("doclint:reference") // cross-module links
    public static <S> ServiceLoader<S> load(Class<S> service,
                                            ClassLoader 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
     * <pre>{@code
     *     ServiceLoader.load(service)
     * }</pre>
     *
     * is equivalent to
     *
     * <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}
     */
    @CallerSensitive
    public static <S> ServiceLoader<S> load(Class<S> service) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);
    }

    /**
     * Creates a new service loader for the given service type, using the
     * {@linkplain ClassLoader#getPlatformClassLoader() platform class loader}.
     *
     * <p> This convenience method is equivalent to: </p>
     *
     * <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 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}
     */
    @CallerSensitive
    public static <S> ServiceLoader<S> loadInstalled(Class<S> service) {
        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
     */
    @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
     */
    public Optional<S> findFirst() {
        Iterator<S> iterator = iterator();
        if (iterator.hasNext()) {
            return Optional.of(iterator.next());
        } else {
            return Optional.empty();
        }
    }

    /**
     * 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() + "]";
    }

}
