/*
 * Copyright (c) 1994, 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.lang;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Console;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.annotation.Annotation;
import java.lang.foreign.MemorySegment;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.module.ModuleDescriptor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.security.ProtectionDomain;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Supplier;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import jdk.internal.javac.Restricted;
import jdk.internal.loader.NativeLibraries;
import jdk.internal.logger.LoggerFinderLoader.TemporaryLoggerFinder;
import jdk.internal.misc.Blocker;
import jdk.internal.misc.CarrierThreadLocal;
import jdk.internal.util.StaticProperty;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.ServicesCatalog;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.logger.LoggerFinderLoader;
import jdk.internal.logger.LazyLoggers;
import jdk.internal.logger.LocalizedLoggerWrapper;
import jdk.internal.misc.VM;
import jdk.internal.util.SystemProps;
import jdk.internal.vm.Continuation;
import jdk.internal.vm.ContinuationScope;
import jdk.internal.vm.StackableScope;
import jdk.internal.vm.ThreadContainer;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import jdk.internal.vm.annotation.Stable;
import sun.reflect.annotation.AnnotationType;
import sun.nio.ch.Interruptible;
import sun.nio.cs.UTF_8;

/**
 * The {@code System} class contains several useful class fields
 * and methods. It cannot be instantiated.
 *
 * Among the facilities provided by the {@code System} class
 * are standard input, standard output, and error output streams;
 * access to externally defined properties and environment
 * variables; a means of loading files and libraries; and a utility
 * method for quickly copying a portion of an array.
 *
 * @since   1.0
 */
public final class System {
    /* Register the natives via the static initializer.
     *
     * The VM will invoke the initPhase1 method to complete the initialization
     * of this class separate from <clinit>.
     */
    private static native void registerNatives();
    static {
        registerNatives();
    }

    /** Don't let anyone instantiate this class */
    private System() {
    }

    /**
     * The "standard" input stream. This stream is already
     * open and ready to supply input data. This stream
     * corresponds to keyboard input or another input source specified by
     * the host environment or user. Applications should use the encoding
     * specified by the {@link ##stdin.encoding stdin.encoding} property
     * to convert input bytes to character data.
     *
     * @apiNote
     * The typical approach to read character data is to wrap {@code System.in}
     * within the object that handles character encoding. After this is done,
     * subsequent reading should use only the wrapper object; continuing to
     * operate directly on {@code System.in} results in unspecified behavior.
     * <p>
     * Here are two common examples. Using an {@link java.io.InputStreamReader
     * InputStreamReader}:
     * {@snippet lang=java :
     *     new InputStreamReader(System.in, System.getProperty("stdin.encoding"));
     * }
     * Or using a {@link java.util.Scanner Scanner}:
     * {@snippet lang=java :
     *     new Scanner(System.in, System.getProperty("stdin.encoding"));
     * }
     * <p>
     * For handling interactive input, consider using {@link Console}.
     *
     * @see Console
     * @see ##stdin.encoding stdin.encoding
     */
    public static final InputStream in = null;

    /**
     * The "standard" output stream. This stream is already
     * open and ready to accept output data. Typically this stream
     * corresponds to display output or another output destination
     * specified by the host environment or user. The encoding used
     * in the conversion from characters to bytes is equivalent to
     * {@link ##stdout.encoding stdout.encoding}.
     * <p>
     * For simple stand-alone Java applications, a typical way to write
     * a line of output data is:
     * <blockquote><pre>
     *     System.out.println(data)
     * </pre></blockquote>
     * <p>
     * See the {@code println} methods in class {@code PrintStream}.
     *
     * @see     java.io.PrintStream#println()
     * @see     java.io.PrintStream#println(boolean)
     * @see     java.io.PrintStream#println(char)
     * @see     java.io.PrintStream#println(char[])
     * @see     java.io.PrintStream#println(double)
     * @see     java.io.PrintStream#println(float)
     * @see     java.io.PrintStream#println(int)
     * @see     java.io.PrintStream#println(long)
     * @see     java.io.PrintStream#println(java.lang.Object)
     * @see     java.io.PrintStream#println(java.lang.String)
     * @see     ##stdout.encoding stdout.encoding
     */
    public static final PrintStream out = null;

    /**
     * The "standard" error output stream. This stream is already
     * open and ready to accept output data.
     * <p>
     * Typically this stream corresponds to display output or another
     * output destination specified by the host environment or user. By
     * convention, this output stream is used to display error messages
     * or other information that should come to the immediate attention
     * of a user even if the principal output stream, the value of the
     * variable {@code out}, has been redirected to a file or other
     * destination that is typically not continuously monitored.
     * The encoding used in the conversion from characters to bytes is
     * equivalent to {@link ##stderr.encoding stderr.encoding}.
     *
     * @see     ##stderr.encoding stderr.encoding
     */
    public static final PrintStream err = null;

    // Initial values of System.in and System.err, set in initPhase1().
    private static @Stable InputStream initialIn;
    private static @Stable PrintStream initialErr;

    // `sun.jnu.encoding` if it is not supported. Otherwise null.
    // It is initialized in `initPhase1()` before any charset providers
    // are initialized.
    private static String notSupportedJnuEncoding;

    /**
     * Reassigns the "standard" input stream.
     *
     * @param in the new standard input stream.
     *
     * @since   1.1
     */
    public static void setIn(InputStream in) {
        setIn0(in);
    }

    /**
     * Reassigns the "standard" output stream.
     *
     * @param out the new standard output stream
     *
     * @since   1.1
     */
    public static void setOut(PrintStream out) {
        setOut0(out);
    }

    /**
     * Reassigns the "standard" error output stream.
     *
     * @param err the new standard error output stream.
     *
     * @since   1.1
     */
    public static void setErr(PrintStream err) {
        setErr0(err);
    }

    private static volatile Console cons;

    /**
     * Returns the unique {@link java.io.Console Console} object associated
     * with the current Java virtual machine, if any.
     *
     * @return  The system console, if any, otherwise {@code null}.
     *
     * @since   1.6
     */
     public static Console console() {
         Console c;
         if ((c = cons) == null) {
             synchronized (System.class) {
                 if ((c = cons) == null) {
                     cons = c = SharedSecrets.getJavaIOAccess().console();
                 }
             }
         }
         return c;
     }

    /**
     * Returns the channel inherited from the entity that created this
     * Java virtual machine.
     *
     * This method returns the channel obtained by invoking the
     * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel
     * inheritedChannel} method of the system-wide default
     * {@link java.nio.channels.spi.SelectorProvider} object.
     *
     * <p> In addition to the network-oriented channels described in
     * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel
     * inheritedChannel}, this method may return other kinds of
     * channels in the future.
     *
     * @return  The inherited channel, if any, otherwise {@code null}.
     *
     * @throws  IOException
     *          If an I/O error occurs
     *
     * @since 1.5
     */
    public static Channel inheritedChannel() throws IOException {
        return SelectorProvider.provider().inheritedChannel();
    }

    private static native void setIn0(InputStream in);
    private static native void setOut0(PrintStream out);
    private static native void setErr0(PrintStream err);

    /**
     * Throws {@code UnsupportedOperationException}. Setting a security manager
     * is not supported.
     *
     * @param  sm ignored
     * @throws UnsupportedOperationException always
     * @see #getSecurityManager
     * @deprecated This method originally set
     *       {@linkplain SecurityManager the system-wide Security Manager}.
     *       Setting a Security Manager is no longer supported. There is no
     *       replacement for the Security Manager or this method.
     */
    @Deprecated(since="17", forRemoval=true)
    public static void setSecurityManager(@SuppressWarnings("removal") SecurityManager sm) {
        throw new UnsupportedOperationException(
                 "Setting a Security Manager is not supported");
    }

    /**
     * Returns {@code null}. Setting a security manager is not supported.
     *
     * @return  {@code null}
     * @see     #setSecurityManager
     * @deprecated This method originally returned
     *       {@linkplain SecurityManager the system-wide Security Manager}.
     *       Setting a Security Manager is no longer supported. There is no
     *       replacement for the Security Manager or this method.
     */
    @SuppressWarnings("removal")
    @Deprecated(since="17", forRemoval=true)
    public static SecurityManager getSecurityManager() {
        return null;
    }

    /**
     * Returns the current time in milliseconds.  Note that
     * while the unit of time of the return value is a millisecond,
     * the granularity of the value depends on the underlying
     * operating system and may be larger.  For example, many
     * operating systems measure time in units of tens of
     * milliseconds.
     *
     * <p> See the description of the class {@code Date} for
     * a discussion of slight discrepancies that may arise between
     * "computer time" and coordinated universal time (UTC).
     *
     * @return  the difference, measured in milliseconds, between
     *          the current time and midnight, January 1, 1970 UTC.
     * @see     java.util.Date
     */
    @IntrinsicCandidate
    public static native long currentTimeMillis();

    /**
     * Returns the current value of the running Java Virtual Machine's
     * high-resolution time source, in nanoseconds.
     *
     * This method can only be used to measure elapsed time and is
     * not related to any other notion of system or wall-clock time.
     * The value returned represents nanoseconds since some fixed but
     * arbitrary <i>origin</i> time (perhaps in the future, so values
     * may be negative).  The same origin is used by all invocations of
     * this method in an instance of a Java virtual machine; other
     * virtual machine instances are likely to use a different origin.
     *
     * <p>This method provides nanosecond precision, but not necessarily
     * nanosecond resolution (that is, how frequently the value changes)
     * - no guarantees are made except that the resolution is at least as
     * good as that of {@link #currentTimeMillis()}.
     *
     * <p>Differences in successive calls that span greater than
     * approximately 292 years (2<sup>63</sup> nanoseconds) will not
     * correctly compute elapsed time due to numerical overflow.
     *
     * <p>The values returned by this method become meaningful only when
     * the difference between two such values, obtained within the same
     * instance of a Java virtual machine, is computed.
     *
     * <p>For example, to measure how long some code takes to execute:
     * <pre> {@code
     * long startTime = System.nanoTime();
     * // ... the code being measured ...
     * long elapsedNanos = System.nanoTime() - startTime;}</pre>
     *
     * <p>To compare elapsed time against a timeout, use <pre> {@code
     * if (System.nanoTime() - startTime >= timeoutNanos) ...}</pre>
     * instead of <pre> {@code
     * if (System.nanoTime() >= startTime + timeoutNanos) ...}</pre>
     * because of the possibility of numerical overflow.
     *
     * @return the current value of the running Java Virtual Machine's
     *         high-resolution time source, in nanoseconds
     * @since 1.5
     */
    @IntrinsicCandidate
    public static native long nanoTime();

    /**
     * Copies an array from the specified source array, beginning at the
     * specified position, to the specified position of the destination array.
     * A subsequence of array components are copied from the source
     * array referenced by {@code src} to the destination array
     * referenced by {@code dest}. The number of components copied is
     * equal to the {@code length} argument. The components at
     * positions {@code srcPos} through
     * {@code srcPos+length-1} in the source array are copied into
     * positions {@code destPos} through
     * {@code destPos+length-1}, respectively, of the destination
     * array.
     * <p>
     * If the {@code src} and {@code dest} arguments refer to the
     * same array object, then the copying is performed as if the
     * components at positions {@code srcPos} through
     * {@code srcPos+length-1} were first copied to a temporary
     * array with {@code length} components and then the contents of
     * the temporary array were copied into positions
     * {@code destPos} through {@code destPos+length-1} of the
     * destination array.
     * <p>
     * If {@code dest} is {@code null}, then a
     * {@code NullPointerException} is thrown.
     * <p>
     * If {@code src} is {@code null}, then a
     * {@code NullPointerException} is thrown and the destination
     * array is not modified.
     * <p>
     * Otherwise, if any of the following is true, an
     * {@code ArrayStoreException} is thrown and the destination is
     * not modified:
     * <ul>
     * <li>The {@code src} argument refers to an object that is not an
     *     array.
     * <li>The {@code dest} argument refers to an object that is not an
     *     array.
     * <li>The {@code src} argument and {@code dest} argument refer
     *     to arrays whose component types are different primitive types.
     * <li>The {@code src} argument refers to an array with a primitive
     *    component type and the {@code dest} argument refers to an array
     *     with a reference component type.
     * <li>The {@code src} argument refers to an array with a reference
     *    component type and the {@code dest} argument refers to an array
     *     with a primitive component type.
     * </ul>
     * <p>
     * Otherwise, if any of the following is true, an
     * {@code IndexOutOfBoundsException} is
     * thrown and the destination is not modified:
     * <ul>
     * <li>The {@code srcPos} argument is negative.
     * <li>The {@code destPos} argument is negative.
     * <li>The {@code length} argument is negative.
     * <li>{@code srcPos+length} is greater than
     *     {@code src.length}, the length of the source array.
     * <li>{@code destPos+length} is greater than
     *     {@code dest.length}, the length of the destination array.
     * </ul>
     * <p>
     * Otherwise, if any actual component of the source array from
     * position {@code srcPos} through
     * {@code srcPos+length-1} cannot be converted to the component
     * type of the destination array by assignment conversion, an
     * {@code ArrayStoreException} is thrown. In this case, let
     * <b><i>k</i></b> be the smallest nonnegative integer less than
     * length such that {@code src[srcPos+}<i>k</i>{@code ]}
     * cannot be converted to the component type of the destination
     * array; when the exception is thrown, source array components from
     * positions {@code srcPos} through
     * {@code srcPos+}<i>k</i>{@code -1}
     * will already have been copied to destination array positions
     * {@code destPos} through
     * {@code destPos+}<i>k</I>{@code -1} and no other
     * positions of the destination array will have been modified.
     * (Because of the restrictions already itemized, this
     * paragraph effectively applies only to the situation where both
     * arrays have component types that are reference types.)
     *
     * @param      src      the source array.
     * @param      srcPos   starting position in the source array.
     * @param      dest     the destination array.
     * @param      destPos  starting position in the destination data.
     * @param      length   the number of array elements to be copied.
     * @throws     IndexOutOfBoundsException  if copying would cause
     *             access of data outside array bounds.
     * @throws     ArrayStoreException  if an element in the {@code src}
     *             array could not be stored into the {@code dest} array
     *             because of a type mismatch.
     * @throws     NullPointerException if either {@code src} or
     *             {@code dest} is {@code null}.
     */
    @IntrinsicCandidate
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

    /**
     * Returns the same hash code for the given object as
     * would be returned by the default method hashCode(),
     * whether or not the given object's class overrides
     * hashCode().
     * The hash code for the null reference is zero.
     *
     * @param x object for which the hashCode is to be calculated
     * @return  the hashCode
     * @since   1.1
     * @see Object#hashCode
     * @see java.util.Objects#hashCode(Object)
     */
    @IntrinsicCandidate
    public static native int identityHashCode(Object x);

    /**
     * System properties.
     *
     * See {@linkplain #getProperties getProperties} for details.
     */
    private static Properties props;

    /**
     * Determines the current system properties.
     * <p>
     * The current set of system properties for use by the
     * {@link #getProperty(String)} method is returned as a
     * {@code Properties} object. If there is no current set of
     * system properties, a set of system properties is first created and
     * initialized. This set of system properties includes a value
     * for each of the following keys unless the description of the associated
     * value indicates that the value is optional.
     * <table class="striped" style="text-align:left">
     * <caption style="display:none">Shows property keys and associated values</caption>
     * <thead>
     * <tr><th scope="col">Key</th>
     *     <th scope="col">Description of Associated Value</th></tr>
     * </thead>
     * <tbody>
     * <tr><th scope="row">{@systemProperty java.version}</th>
     *     <td>Java Runtime Environment version, which may be interpreted
     *     as a {@link Runtime.Version}</td></tr>
     * <tr><th scope="row">{@systemProperty java.version.date}</th>
     *     <td>Java Runtime Environment version date, in ISO-8601 YYYY-MM-DD
     *     format, which may be interpreted as a {@link
     *     java.time.LocalDate}</td></tr>
     * <tr><th scope="row">{@systemProperty java.vendor}</th>
     *     <td>Java Runtime Environment vendor</td></tr>
     * <tr><th scope="row">{@systemProperty java.vendor.url}</th>
     *     <td>Java vendor URL</td></tr>
     * <tr><th scope="row">{@systemProperty java.vendor.version}</th>
     *     <td>Java vendor version <em>(optional)</em> </td></tr>
     * <tr><th scope="row">{@systemProperty java.home}</th>
     *     <td>Java installation directory</td></tr>
     * <tr><th scope="row">{@systemProperty java.vm.specification.version}</th>
     *     <td>Java Virtual Machine specification version, whose value is the
     *     {@linkplain Runtime.Version#feature feature} element of the
     *     {@linkplain Runtime#version() runtime version}</td></tr>
     * <tr><th scope="row">{@systemProperty java.vm.specification.vendor}</th>
     *     <td>Java Virtual Machine specification vendor</td></tr>
     * <tr><th scope="row">{@systemProperty java.vm.specification.name}</th>
     *     <td>Java Virtual Machine specification name</td></tr>
     * <tr><th scope="row">{@systemProperty java.vm.version}</th>
     *     <td>Java Virtual Machine implementation version which may be
     *     interpreted as a {@link Runtime.Version}</td></tr>
     * <tr><th scope="row">{@systemProperty java.vm.vendor}</th>
     *     <td>Java Virtual Machine implementation vendor</td></tr>
     * <tr><th scope="row">{@systemProperty java.vm.name}</th>
     *     <td>Java Virtual Machine implementation name</td></tr>
     * <tr><th scope="row">{@systemProperty java.specification.version}</th>
     *     <td>Java Runtime Environment specification version, whose value is
     *     the {@linkplain Runtime.Version#feature feature} element of the
     *     {@linkplain Runtime#version() runtime version}</td></tr>
     * <tr><th scope="row">{@systemProperty java.specification.maintenance.version}</th>
     *     <td>Java Runtime Environment specification maintenance version,
     *     may be interpreted as a positive integer <em>(optional, see below)</em></td></tr>
     * <tr><th scope="row">{@systemProperty java.specification.vendor}</th>
     *     <td>Java Runtime Environment specification  vendor</td></tr>
     * <tr><th scope="row">{@systemProperty java.specification.name}</th>
     *     <td>Java Runtime Environment specification  name</td></tr>
     * <tr><th scope="row">{@systemProperty java.class.version}</th>
     *     <td>{@linkplain java.lang.reflect.ClassFileFormatVersion#latest() Latest}
     *     Java class file format version recognized by the Java runtime as {@code "MAJOR.MINOR"}
     *     where {@link java.lang.reflect.ClassFileFormatVersion#major() MAJOR} and {@code MINOR}
     *     are both formatted as decimal integers</td></tr>
     * <tr><th scope="row">{@systemProperty java.class.path}</th>
     *     <td>Java class path  (refer to
     *        {@link ClassLoader#getSystemClassLoader()} for details)</td></tr>
     * <tr><th scope="row">{@systemProperty java.library.path}</th>
     *     <td>List of paths to search when loading libraries</td></tr>
     * <tr><th scope="row">{@systemProperty java.io.tmpdir}</th>
     *     <td>Default temp file path</td></tr>
     * <tr><th scope="row">{@systemProperty os.name}</th>
     *     <td>Operating system name</td></tr>
     * <tr><th scope="row">{@systemProperty os.arch}</th>
     *     <td>Operating system architecture</td></tr>
     * <tr><th scope="row">{@systemProperty os.version}</th>
     *     <td>Operating system version</td></tr>
     * <tr><th scope="row">{@systemProperty file.separator}</th>
     *     <td>File separator ("/" on UNIX)</td></tr>
     * <tr><th scope="row">{@systemProperty path.separator}</th>
     *     <td>Path separator (":" on UNIX)</td></tr>
     * <tr><th scope="row">{@systemProperty line.separator}</th>
     *     <td>Line separator ("\n" on UNIX)</td></tr>
     * <tr><th scope="row">{@systemProperty user.name}</th>
     *     <td>User's account name</td></tr>
     * <tr><th scope="row">{@systemProperty user.home}</th>
     *     <td>User's home directory</td></tr>
     * <tr><th scope="row">{@systemProperty user.dir}</th>
     *     <td>User's current working directory</td></tr>
     * <tr><th scope="row">{@systemProperty native.encoding}</th>
     *     <td>Character encoding name derived from the host environment and
     *     the user's settings. Setting this system property on the command line
     *     has no effect.</td></tr>
     * <tr><th scope="row">{@systemProperty stdin.encoding}</th>
     *     <td>Character encoding name for {@link System#in System.in}.
     *     The Java runtime can be started with the system property set to {@code UTF-8}.
     *     Starting it with the property set to another value results in unspecified behavior.
     * <tr><th scope="row">{@systemProperty stdout.encoding}</th>
     *     <td>Character encoding name for {@link System#out System.out} and
     *     {@link System#console() System.console()}.
     *     The Java runtime can be started with the system property set to {@code UTF-8}.
     *     Starting it with the property set to another value results in unspecified behavior.
     * <tr><th scope="row">{@systemProperty stderr.encoding}</th>
     *     <td>Character encoding name for {@link System#err System.err}.
     *     The Java runtime can be started with the system property set to {@code UTF-8}.
     *     Starting it with the property set to another value results in unspecified behavior.
     * </tbody>
     * </table>
     * <p>
     * The {@code java.specification.maintenance.version} property is
     * defined if the specification implemented by this runtime at the
     * time of its construction had undergone a <a
     * href="https://jcp.org/en/procedures/jcp2#3.6.4">maintenance
     * release</a>. When defined, its value identifies that
     * maintenance release. To indicate the first maintenance release
     * this property will have the value {@code "1"}, to indicate the
     * second maintenance release this property will have the value
     * {@code "2"}, and so on.
     * <p>
     * Multiple paths in a system property value are separated by the path
     * separator character of the platform.
     * <p>
     * Additional locale-related system properties defined by the
     * {@link Locale##default_locale Default Locale} section in the {@code Locale}
     * class description may also be obtained with this method.
     *
     * @apiNote
     * <strong>Changing a standard system property may have unpredictable results
     * unless otherwise specified.</strong>
     * Property values may be cached during initialization or on first use.
     * Setting a standard property after initialization using {@link #getProperties()},
     * {@link #setProperties(Properties)}, {@link #setProperty(String, String)}, or
     * {@link #clearProperty(String)} may not have the desired effect.
     *
     * @implNote
     * In addition to the standard system properties, the system
     * properties may include the following keys:
     * <table class="striped">
     * <caption style="display:none">Shows property keys and associated values</caption>
     * <thead>
     * <tr><th scope="col">Key</th>
     *     <th scope="col">Description of Associated Value</th></tr>
     * </thead>
     * <tbody>
     * <tr><th scope="row">{@systemProperty jdk.module.path}</th>
     *     <td>The application module path</td></tr>
     * <tr><th scope="row">{@systemProperty jdk.module.upgrade.path}</th>
     *     <td>The upgrade module path</td></tr>
     * <tr><th scope="row">{@systemProperty jdk.module.main}</th>
     *     <td>The module name of the initial/main module</td></tr>
     * <tr><th scope="row">{@systemProperty jdk.module.main.class}</th>
     *     <td>The main class name of the initial module</td></tr>
     * <tr><th scope="row">{@systemProperty file.encoding}</th>
     *     <td>The name of the default charset, defaults to {@code UTF-8}.
     *     The property may be set on the command line to the value
     *     {@code UTF-8} or {@code COMPAT}. If set on the command line to
     *     the value {@code COMPAT} then the value is replaced with the
     *     value of the {@code native.encoding} property during startup.
     *     Setting the property to a value other than {@code UTF-8} or
     *     {@code COMPAT} results in unspecified behavior.
     *     </td></tr>
     * </tbody>
     * </table>
     *
     * @return     the system properties
     * @see        #setProperties
     * @see        java.util.Properties
     */
    public static Properties getProperties() {
        return props;
    }

    /**
     * Returns the system-dependent line separator string.  It always
     * returns the same value - the initial value of the {@linkplain
     * #getProperty(String) system property} {@code line.separator}.
     *
     * <p>On UNIX systems, it returns {@code "\n"}; on Microsoft
     * Windows systems it returns {@code "\r\n"}.
     *
     * @return the system-dependent line separator string
     * @since 1.7
     */
    public static String lineSeparator() {
        return lineSeparator;
    }

    private static String lineSeparator;

    /**
     * Sets the system properties to the {@code Properties} argument.
     * <p>
     * The argument becomes the current set of system properties for use
     * by the {@link #getProperty(String)} method. If the argument is
     * {@code null}, then the current set of system properties is
     * forgotten.
     *
     * @apiNote
     * <strong>Changing a standard system property may have unpredictable results
     * unless otherwise specified</strong>.
     * See {@linkplain #getProperties getProperties} for details.
     *
     * @param      props   the new system properties.
     * @see        #getProperties
     * @see        java.util.Properties
     */
    public static void setProperties(Properties props) {
        if (props == null) {
            Map<String, String> tempProps = SystemProps.initProperties();
            VersionProps.init(tempProps);
            props = createProperties(tempProps);
        }
        System.props = props;
    }

    /**
     * Gets the system property indicated by the specified key.
     * <p>
     * If there is no current set of system properties, a set of system
     * properties is first created and initialized in the same manner as
     * for the {@code getProperties} method.
     *
     * @apiNote
     * <strong>Changing a standard system property may have unpredictable results
     * unless otherwise specified</strong>.
     * See {@linkplain #getProperties getProperties} for details.
     *
     * @param      key   the name of the system property.
     * @return     the string value of the system property,
     *             or {@code null} if there is no property with that key.
     *
     * @throws     NullPointerException if {@code key} is {@code null}.
     * @throws     IllegalArgumentException if {@code key} is empty.
     * @see        #setProperty
     * @see        java.lang.System#getProperties()
     */
    public static String getProperty(String key) {
        checkKey(key);
        return props.getProperty(key);
    }

    /**
     * Gets the system property indicated by the specified key.
     * <p>
     * If there is no current set of system properties, a set of system
     * properties is first created and initialized in the same manner as
     * for the {@code getProperties} method.
     *
     * @param      key   the name of the system property.
     * @param      def   a default value.
     * @return     the string value of the system property,
     *             or the default value if there is no property with that key.
     *
     * @throws     NullPointerException if {@code key} is {@code null}.
     * @throws     IllegalArgumentException if {@code key} is empty.
     * @see        #setProperty
     * @see        java.lang.System#getProperties()
     */
    public static String getProperty(String key, String def) {
        checkKey(key);
        return props.getProperty(key, def);
    }

    /**
     * Sets the system property indicated by the specified key.
     *
     * @apiNote
     * <strong>Changing a standard system property may have unpredictable results
     * unless otherwise specified</strong>.
     * See {@linkplain #getProperties getProperties} for details.
     *
     * @param      key   the name of the system property.
     * @param      value the value of the system property.
     * @return     the previous value of the system property,
     *             or {@code null} if it did not have one.
     *
     * @throws     NullPointerException if {@code key} or
     *             {@code value} is {@code null}.
     * @throws     IllegalArgumentException if {@code key} is empty.
     * @see        #getProperty
     * @see        java.lang.System#getProperty(java.lang.String)
     * @see        java.lang.System#getProperty(java.lang.String, java.lang.String)
     * @since      1.2
     */
    public static String setProperty(String key, String value) {
        checkKey(key);
        return (String) props.setProperty(key, value);
    }

    /**
     * Removes the system property indicated by the specified key.
     *
     * @apiNote
     * <strong>Changing a standard system property may have unpredictable results
     * unless otherwise specified</strong>.
     * See {@linkplain #getProperties getProperties} method for details.
     *
     * @param      key   the name of the system property to be removed.
     * @return     the previous string value of the system property,
     *             or {@code null} if there was no property with that key.
     *
     * @throws     NullPointerException if {@code key} is {@code null}.
     * @throws     IllegalArgumentException if {@code key} is empty.
     * @see        #getProperty
     * @see        #setProperty
     * @see        java.util.Properties
     * @since 1.5
     */
    public static String clearProperty(String key) {
        checkKey(key);
        return (String) props.remove(key);
    }

    private static void checkKey(String key) {
        if (key == null) {
            throw new NullPointerException("key can't be null");
        }
        if (key.isEmpty()) {
            throw new IllegalArgumentException("key can't be empty");
        }
    }

    /**
     * Gets the value of the specified environment variable. An
     * environment variable is a system-dependent external named
     * value.
     *
     * <p><a id="EnvironmentVSSystemProperties"><i>System
     * properties</i> and <i>environment variables</i></a> are both
     * conceptually mappings between names and values.  Both
     * mechanisms can be used to pass user-defined information to a
     * Java process.  Environment variables have a more global effect,
     * because they are visible to all descendants of the process
     * which defines them, not just the immediate Java subprocess.
     * They can have subtly different semantics, such as case
     * insensitivity, on different operating systems.  For these
     * reasons, environment variables are more likely to have
     * unintended side effects.  It is best to use system properties
     * where possible.  Environment variables should be used when a
     * global effect is desired, or when an external system interface
     * requires an environment variable (such as {@code PATH}).
     *
     * <p>On UNIX systems the alphabetic case of {@code name} is
     * typically significant, while on Microsoft Windows systems it is
     * typically not.  For example, the expression
     * {@code System.getenv("FOO").equals(System.getenv("foo"))}
     * is likely to be true on Microsoft Windows.
     *
     * @param  name the name of the environment variable
     * @return the string value of the variable, or {@code null}
     *         if the variable is not defined in the system environment
     * @throws NullPointerException if {@code name} is {@code null}
     * @see    #getenv()
     * @see    ProcessBuilder#environment()
     */
    public static String getenv(String name) {
        return ProcessEnvironment.getenv(name);
    }


    /**
     * Returns an unmodifiable string map view of the current system environment.
     * The environment is a system-dependent mapping from names to
     * values which is passed from parent to child processes.
     *
     * <p>If the system does not support environment variables, an
     * empty map is returned.
     *
     * <p>The returned map will never contain null keys or values.
     * Attempting to query the presence of a null key or value will
     * throw a {@link NullPointerException}.  Attempting to query
     * the presence of a key or value which is not of type
     * {@link String} will throw a {@link ClassCastException}.
     *
     * <p>The returned map and its collection views may not obey the
     * general contract of the {@link Object#equals} and
     * {@link Object#hashCode} methods.
     *
     * <p>The returned map is typically case-sensitive on all platforms.
     *
     * <p>When passing information to a Java subprocess,
     * <a href=#EnvironmentVSSystemProperties>system properties</a>
     * are generally preferred over environment variables.
     *
     * @return the environment as a map of variable names to values
     * @see    #getenv(String)
     * @see    ProcessBuilder#environment()
     * @since  1.5
     */
    public static java.util.Map<String,String> getenv() {
        return ProcessEnvironment.getenv();
    }

    /**
     * {@code System.Logger} instances log messages that will be
     * routed to the underlying logging framework the {@link System.LoggerFinder
     * LoggerFinder} uses.
     *
     * {@code System.Logger} instances are typically obtained from
     * the {@link java.lang.System System} class, by calling
     * {@link java.lang.System#getLogger(java.lang.String) System.getLogger(loggerName)}
     * or {@link java.lang.System#getLogger(java.lang.String, java.util.ResourceBundle)
     * System.getLogger(loggerName, bundle)}.
     *
     * @see java.lang.System#getLogger(java.lang.String)
     * @see java.lang.System#getLogger(java.lang.String, java.util.ResourceBundle)
     * @see java.lang.System.LoggerFinder
     *
     * @since 9
     */
    public interface Logger {

        /**
         * System {@linkplain Logger loggers} levels.
         *
         * A level has a {@linkplain #getName() name} and {@linkplain
         * #getSeverity() severity}.
         * Level values are {@link #ALL}, {@link #TRACE}, {@link #DEBUG},
         * {@link #INFO}, {@link #WARNING}, {@link #ERROR}, {@link #OFF},
         * by order of increasing severity.
         * <br>
         * {@link #ALL} and {@link #OFF}
         * are simple markers with severities mapped respectively to
         * {@link java.lang.Integer#MIN_VALUE Integer.MIN_VALUE} and
         * {@link java.lang.Integer#MAX_VALUE Integer.MAX_VALUE}.
         * <p>
         * <b>Severity values and Mapping to {@code java.util.logging.Level}.</b>
         * <p>
         * {@linkplain System.Logger.Level System logger levels} are mapped to
         * {@linkplain java.logging/java.util.logging.Level  java.util.logging levels}
         * of corresponding severity.
         * <br>The mapping is as follows:
         * <br><br>
         * <table class="striped">
         * <caption>System.Logger Severity Level Mapping</caption>
         * <thead>
         * <tr><th scope="col">System.Logger Levels</th>
         *     <th scope="col">java.util.logging Levels</th>
         * </thead>
         * <tbody>
         * <tr><th scope="row">{@link Logger.Level#ALL ALL}</th>
         *     <td>{@link java.logging/java.util.logging.Level#ALL ALL}</td>
         * <tr><th scope="row">{@link Logger.Level#TRACE TRACE}</th>
         *     <td>{@link java.logging/java.util.logging.Level#FINER FINER}</td>
         * <tr><th scope="row">{@link Logger.Level#DEBUG DEBUG}</th>
         *     <td>{@link java.logging/java.util.logging.Level#FINE FINE}</td>
         * <tr><th scope="row">{@link Logger.Level#INFO INFO}</th>
         *     <td>{@link java.logging/java.util.logging.Level#INFO INFO}</td>
         * <tr><th scope="row">{@link Logger.Level#WARNING WARNING}</th>
         *     <td>{@link java.logging/java.util.logging.Level#WARNING WARNING}</td>
         * <tr><th scope="row">{@link Logger.Level#ERROR ERROR}</th>
         *     <td>{@link java.logging/java.util.logging.Level#SEVERE SEVERE}</td>
         * <tr><th scope="row">{@link Logger.Level#OFF OFF}</th>
         *     <td>{@link java.logging/java.util.logging.Level#OFF OFF}</td>
         * </tbody>
         * </table>
         *
         * @since 9
         *
         * @see java.lang.System.LoggerFinder
         * @see java.lang.System.Logger
         */
        @SuppressWarnings("doclint:reference") // cross-module links
        public enum Level {

            // for convenience, we're reusing java.util.logging.Level int values
            // the mapping logic in sun.util.logging.PlatformLogger depends
            // on this.
            /**
             * A marker to indicate that all levels are enabled.
             * This level {@linkplain #getSeverity() severity} is
             * {@link Integer#MIN_VALUE}.
             */
            ALL(Integer.MIN_VALUE),  // typically mapped to/from j.u.l.Level.ALL
            /**
             * {@code TRACE} level: usually used to log diagnostic information.
             * This level {@linkplain #getSeverity() severity} is
             * {@code 400}.
             */
            TRACE(400),   // typically mapped to/from j.u.l.Level.FINER
            /**
             * {@code DEBUG} level: usually used to log debug information traces.
             * This level {@linkplain #getSeverity() severity} is
             * {@code 500}.
             */
            DEBUG(500),   // typically mapped to/from j.u.l.Level.FINEST/FINE/CONFIG
            /**
             * {@code INFO} level: usually used to log information messages.
             * This level {@linkplain #getSeverity() severity} is
             * {@code 800}.
             */
            INFO(800),    // typically mapped to/from j.u.l.Level.INFO
            /**
             * {@code WARNING} level: usually used to log warning messages.
             * This level {@linkplain #getSeverity() severity} is
             * {@code 900}.
             */
            WARNING(900), // typically mapped to/from j.u.l.Level.WARNING
            /**
             * {@code ERROR} level: usually used to log error messages.
             * This level {@linkplain #getSeverity() severity} is
             * {@code 1000}.
             */
            ERROR(1000),  // typically mapped to/from j.u.l.Level.SEVERE
            /**
             * A marker to indicate that all levels are disabled.
             * This level {@linkplain #getSeverity() severity} is
             * {@link Integer#MAX_VALUE}.
             */
            OFF(Integer.MAX_VALUE);  // typically mapped to/from j.u.l.Level.OFF

            private final int severity;

            private Level(int severity) {
                this.severity = severity;
            }

            /**
             * Returns the name of this level.
             * @return this level {@linkplain #name()}.
             */
            public final String getName() {
                return name();
            }

            /**
             * Returns the severity of this level.
             * A higher severity means a more severe condition.
             * @return this level severity.
             */
            public final int getSeverity() {
                return severity;
            }
        }

        /**
         * Returns the name of this logger.
         *
         * @return the logger name.
         */
        public String getName();

        /**
         * Checks if a message of the given level would be logged by
         * this logger.
         *
         * @param level the log message level.
         * @return {@code true} if the given log message level is currently
         *         being logged.
         *
         * @throws NullPointerException if {@code level} is {@code null}.
         */
        public boolean isLoggable(Level level);

        /**
         * Logs a message.
         *
         * @implSpec The default implementation for this method calls
         * {@code this.log(level, (ResourceBundle)null, msg, (Object[])null);}
         *
         * @param level the log message level.
         * @param msg the string message (or a key in the message catalog, if
         * this logger is a {@link
         * LoggerFinder#getLocalizedLogger(java.lang.String,
         * java.util.ResourceBundle, java.lang.Module) localized logger});
         * can be {@code null}.
         *
         * @throws NullPointerException if {@code level} is {@code null}.
         */
        public default void log(Level level, String msg) {
            log(level, (ResourceBundle) null, msg, (Object[]) null);
        }

        /**
         * Logs a lazily supplied message.
         *
         * If the logger is currently enabled for the given log message level
         * then a message is logged that is the result produced by the
         * given supplier function.  Otherwise, the supplier is not operated on.
         *
         * @implSpec When logging is enabled for the given level, the default
         * implementation for this method calls
         * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), (Object[])null);}
         *
         * @param level the log message level.
         * @param msgSupplier a supplier function that produces a message.
         *
         * @throws NullPointerException if {@code level} is {@code null},
         *         or {@code msgSupplier} is {@code null}.
         */
        public default void log(Level level, Supplier<String> msgSupplier) {
            Objects.requireNonNull(msgSupplier);
            if (isLoggable(Objects.requireNonNull(level))) {
                log(level, (ResourceBundle) null, msgSupplier.get(), (Object[]) null);
            }
        }

        /**
         * Logs a message produced from the given object.
         *
         * If the logger is currently enabled for the given log message level then
         * a message is logged that, by default, is the result produced from
         * calling  toString on the given object.
         * Otherwise, the object is not operated on.
         *
         * @implSpec When logging is enabled for the given level, the default
         * implementation for this method calls
         * {@code this.log(level, (ResourceBundle)null, obj.toString(), (Object[])null);}
         *
         * @param level the log message level.
         * @param obj the object to log.
         *
         * @throws NullPointerException if {@code level} is {@code null}, or
         *         {@code obj} is {@code null}.
         */
        public default void log(Level level, Object obj) {
            Objects.requireNonNull(obj);
            if (isLoggable(Objects.requireNonNull(level))) {
                this.log(level, (ResourceBundle) null, obj.toString(), (Object[]) null);
            }
        }

        /**
         * Logs a message associated with a given throwable.
         *
         * @implSpec The default implementation for this method calls
         * {@code this.log(level, (ResourceBundle)null, msg, thrown);}
         *
         * @param level the log message level.
         * @param msg the string message (or a key in the message catalog, if
         * this logger is a {@link
         * LoggerFinder#getLocalizedLogger(java.lang.String,
         * java.util.ResourceBundle, java.lang.Module) localized logger});
         * can be {@code null}.
         * @param thrown a {@code Throwable} associated with the log message;
         *        can be {@code null}.
         *
         * @throws NullPointerException if {@code level} is {@code null}.
         */
        public default void log(Level level, String msg, Throwable thrown) {
            this.log(level, null, msg, thrown);
        }

        /**
         * Logs a lazily supplied message associated with a given throwable.
         *
         * If the logger is currently enabled for the given log message level
         * then a message is logged that is the result produced by the
         * given supplier function.  Otherwise, the supplier is not operated on.
         *
         * @implSpec When logging is enabled for the given level, the default
         * implementation for this method calls
         * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), thrown);}
         *
         * @param level one of the log message level identifiers.
         * @param msgSupplier a supplier function that produces a message.
         * @param thrown a {@code Throwable} associated with log message;
         *               can be {@code null}.
         *
         * @throws NullPointerException if {@code level} is {@code null}, or
         *                               {@code msgSupplier} is {@code null}.
         */
        public default void log(Level level, Supplier<String> msgSupplier,
                Throwable thrown) {
            Objects.requireNonNull(msgSupplier);
            if (isLoggable(Objects.requireNonNull(level))) {
                this.log(level, null, msgSupplier.get(), thrown);
            }
        }

        /**
         * Logs a message with an optional list of parameters.
         *
         * @implSpec The default implementation for this method calls
         * {@code this.log(level, (ResourceBundle)null, format, params);}
         *
         * @param level one of the log message level identifiers.
         * @param format the string message format in {@link
         * java.text.MessageFormat} format, (or a key in the message
         * catalog, if this logger is a {@link
         * LoggerFinder#getLocalizedLogger(java.lang.String,
         * java.util.ResourceBundle, java.lang.Module) localized logger});
         * can be {@code null}.
         * @param params an optional list of parameters to the message (may be
         * none).
         *
         * @throws NullPointerException if {@code level} is {@code null}.
         */
        public default void log(Level level, String format, Object... params) {
            this.log(level, null, format, params);
        }

        /**
         * Logs a localized message associated with a given throwable.
         *
         * If the given resource bundle is non-{@code null},  the {@code msg}
         * string is localized using the given resource bundle.
         * Otherwise the {@code msg} string is not localized.
         *
         * @param level the log message level.
         * @param bundle a resource bundle to localize {@code msg}; can be
         * {@code null}.
         * @param msg the string message (or a key in the message catalog,
         *            if {@code bundle} is not {@code null}); can be {@code null}.
         * @param thrown a {@code Throwable} associated with the log message;
         *        can be {@code null}.
         *
         * @throws NullPointerException if {@code level} is {@code null}.
         */
        public void log(Level level, ResourceBundle bundle, String msg,
                Throwable thrown);

        /**
         * Logs a message with resource bundle and an optional list of
         * parameters.
         *
         * If the given resource bundle is non-{@code null},  the {@code format}
         * string is localized using the given resource bundle.
         * Otherwise the {@code format} string is not localized.
         *
         * @param level the log message level.
         * @param bundle a resource bundle to localize {@code format}; can be
         * {@code null}.
         * @param format the string message format in {@link
         * java.text.MessageFormat} format, (or a key in the message
         * catalog if {@code bundle} is not {@code null}); can be {@code null}.
         * @param params an optional list of parameters to the message (may be
         * none).
         *
         * @throws NullPointerException if {@code level} is {@code null}.
         */
        public void log(Level level, ResourceBundle bundle, String format,
                Object... params);
    }

    /**
     * The {@code LoggerFinder} service is responsible for creating, managing,
     * and configuring loggers to the underlying framework it uses.
     *
     * A logger finder is a concrete implementation of this class that has a
     * zero-argument constructor and implements the abstract methods defined
     * by this class.
     * The loggers returned from a logger finder are capable of routing log
     * messages to the logging backend this provider supports.
     * A given invocation of the Java Runtime maintains a single
     * system-wide LoggerFinder instance that is loaded as follows:
     * <ul>
     *    <li>First it finds any custom {@code LoggerFinder} provider
     *        using the {@link java.util.ServiceLoader} facility with the
     *        {@linkplain ClassLoader#getSystemClassLoader() system class
     *        loader}.</li>
     *    <li>If no {@code LoggerFinder} provider is found, the system default
     *        {@code LoggerFinder} implementation will be used.</li>
     * </ul>
     * <p>
     * An application can replace the logging backend
     * <i>even when the java.logging module is present</i>, by simply providing
     * and declaring an implementation of the {@link LoggerFinder} service.
     * <p>
     * <b>Default Implementation</b>
     * <p>
     * The system default {@code LoggerFinder} implementation uses
     * {@code java.util.logging} as the backend framework when the
     * {@code java.logging} module is present.
     * It returns a {@linkplain System.Logger logger} instance
     * that will route log messages to a {@link java.logging/java.util.logging.Logger
     * java.util.logging.Logger}. Otherwise, if {@code java.logging} is not
     * present, the default implementation will return a simple logger
     * instance that will route log messages of {@code INFO} level and above to
     * the console ({@code System.err}).
     * <p>
     * <b>Logging Configuration</b>
     * <p>
     * {@linkplain Logger Logger} instances obtained from the
     * {@code LoggerFinder} factory methods are not directly configurable by
     * the application. Configuration is the responsibility of the underlying
     * logging backend, and usually requires using APIs specific to that backend.
     * <p>For the default {@code LoggerFinder} implementation
     * using {@code java.util.logging} as its backend, refer to
     * {@link java.logging/java.util.logging java.util.logging} for logging configuration.
     * For the default {@code LoggerFinder} implementation returning simple loggers
     * when the {@code java.logging} module is absent, the configuration
     * is implementation dependent.
     * <p>
     * Usually an application that uses a logging framework will log messages
     * through a logger facade defined (or supported) by that framework.
     * Applications that wish to use an external framework should log
     * through the facade associated with that framework.
     * <p>
     * A system class that needs to log messages will typically obtain
     * a {@link System.Logger} instance to route messages to the logging
     * framework selected by the application.
     * <p>
     * Libraries and classes that only need loggers to produce log messages
     * should not attempt to configure loggers by themselves, as that
     * would make them dependent from a specific implementation of the
     * {@code LoggerFinder} service.
     * <p>
     * <b>Message Levels and Mapping to backend levels</b>
     * <p>
     * A logger finder is responsible for mapping from a {@code
     * System.Logger.Level} to a level supported by the logging backend it uses.
     * <br>The default LoggerFinder using {@code java.util.logging} as the backend
     * maps {@code System.Logger} levels to
     * {@linkplain java.logging/java.util.logging.Level java.util.logging} levels
     * of corresponding severity - as described in {@link Logger.Level
     * Logger.Level}.
     *
     * @see java.lang.System
     * @see java.lang.System.Logger
     *
     * @since 9
     */
    @SuppressWarnings("doclint:reference") // cross-module links
    public abstract static class LoggerFinder {

        /**
         * Creates a new instance of {@code LoggerFinder}.
         *
         * @implNote It is recommended that a {@code LoggerFinder} service
         *   implementation does not perform any heavy initialization in its
         *   constructor, in order to avoid possible risks of deadlock or class
         *   loading cycles during the instantiation of the service provider.
         */
        protected LoggerFinder() {
        }

        /**
         * Returns an instance of {@link Logger Logger}
         * for the given {@code module}.
         *
         * @param name the name of the logger.
         * @param module the module for which the logger is being requested.
         *
         * @return a {@link Logger logger} suitable for use within the given
         *         module.
         * @throws NullPointerException if {@code name} is {@code null} or
         *        {@code module} is {@code null}.
         */
        public abstract Logger getLogger(String name, Module module);

        /**
         * Returns a localizable instance of {@link Logger Logger}
         * for the given {@code module}.
         * The returned logger will use the provided resource bundle for
         * message localization.
         *
         * @implSpec By default, this method calls {@link
         * #getLogger(java.lang.String, java.lang.Module)
         * this.getLogger(name, module)} to obtain a logger, then wraps that
         * logger in a {@link Logger} instance where all methods that do not
         * take a {@link ResourceBundle} as parameter are redirected to one
         * which does - passing the given {@code bundle} for
         * localization. So for instance, a call to {@link
         * Logger#log(Logger.Level, String) Logger.log(Level.INFO, msg)}
         * will end up as a call to {@link
         * Logger#log(Logger.Level, ResourceBundle, String, Object...)
         * Logger.log(Level.INFO, bundle, msg, (Object[])null)} on the wrapped
         * logger instance.
         * Note however that by default, string messages returned by {@link
         * java.util.function.Supplier Supplier&lt;String&gt;} will not be
         * localized, as it is assumed that such strings are messages which are
         * already constructed, rather than keys in a resource bundle.
         * <p>
         * An implementation of {@code LoggerFinder} may override this method,
         * for example, when the underlying logging backend provides its own
         * mechanism for localizing log messages, then such a
         * {@code LoggerFinder} would be free to return a logger
         * that makes direct use of the mechanism provided by the backend.
         *
         * @param name    the name of the logger.
         * @param bundle  a resource bundle; can be {@code null}.
         * @param module  the module for which the logger is being requested.
         * @return an instance of {@link Logger Logger}  which will use the
         * provided resource bundle for message localization.
         *
         * @throws NullPointerException if {@code name} is {@code null} or
         *         {@code module} is {@code null}.
         */
        public Logger getLocalizedLogger(String name, ResourceBundle bundle,
                                         Module module) {
            return new LocalizedLoggerWrapper<>(getLogger(name, module), bundle);
        }

        /**
         * Returns the {@code LoggerFinder} instance. There is one
         * single system-wide {@code LoggerFinder} instance in
         * the Java Runtime.  See the class specification of how the
         * {@link LoggerFinder LoggerFinder} implementation is located and
         * loaded.
         *
         * @return the {@link LoggerFinder LoggerFinder} instance.
         */
        public static LoggerFinder getLoggerFinder() {
            return accessProvider();
        }


        private static volatile LoggerFinder service;
        static LoggerFinder accessProvider() {
            // We do not need to synchronize: LoggerFinderLoader will
            // always return the same instance, so if we don't have it,
            // just fetch it again.
            LoggerFinder finder = service;
            if (finder == null) {
                finder = LoggerFinderLoader.getLoggerFinder();
                if (finder instanceof TemporaryLoggerFinder) return finder;
                service = finder;
            }
            return finder;
        }

    }


    /**
     * Returns an instance of {@link Logger Logger} for the caller's
     * use.
     *
     * @implSpec
     * Instances returned by this method route messages to loggers
     * obtained by calling {@link LoggerFinder#getLogger(java.lang.String,
     * java.lang.Module) LoggerFinder.getLogger(name, module)}, where
     * {@code module} is the caller's module.
     * In cases where {@code System.getLogger} is called from a context where
     * there is no caller frame on the stack (e.g when called directly
     * from a JNI attached thread), {@code IllegalCallerException} is thrown.
     * To obtain a logger in such a context, use an auxiliary class that will
     * implicitly be identified as the caller, or use the system {@link
     * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead.
     * Note that doing the latter may eagerly initialize the underlying
     * logging system.
     *
     * @apiNote
     * This method may defer calling the {@link
     * LoggerFinder#getLogger(java.lang.String, java.lang.Module)
     * LoggerFinder.getLogger} method to create an actual logger supplied by
     * the logging backend, for instance, to allow loggers to be obtained during
     * the system initialization time.
     *
     * @param name the name of the logger.
     * @return an instance of {@link Logger} that can be used by the calling
     *         class.
     * @throws NullPointerException if {@code name} is {@code null}.
     * @throws IllegalCallerException if there is no Java caller frame on the
     *         stack.
     *
     * @since 9
     */
    @CallerSensitive
    public static Logger getLogger(String name) {
        Objects.requireNonNull(name);
        final Class<?> caller = Reflection.getCallerClass();
        if (caller == null) {
            throw new IllegalCallerException("no caller frame");
        }
        return LazyLoggers.getLogger(name, caller.getModule());
    }

    /**
     * Returns a localizable instance of {@link Logger
     * Logger} for the caller's use.
     * The returned logger will use the provided resource bundle for message
     * localization.
     *
     * @implSpec
     * The returned logger will perform message localization as specified
     * by {@link LoggerFinder#getLocalizedLogger(java.lang.String,
     * java.util.ResourceBundle, java.lang.Module)
     * LoggerFinder.getLocalizedLogger(name, bundle, module)}, where
     * {@code module} is the caller's module.
     * In cases where {@code System.getLogger} is called from a context where
     * there is no caller frame on the stack (e.g when called directly
     * from a JNI attached thread), {@code IllegalCallerException} is thrown.
     * To obtain a logger in such a context, use an auxiliary class that
     * will implicitly be identified as the caller, or use the system {@link
     * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead.
     * Note that doing the latter may eagerly initialize the underlying
     * logging system.
     *
     * @apiNote
     * This method is intended to be used after the system is fully initialized.
     * This method may trigger the immediate loading and initialization
     * of the {@link LoggerFinder} service, which may cause issues if the
     * Java Runtime is not ready to initialize the concrete service
     * implementation yet.
     * System classes which may be loaded early in the boot sequence and
     * need to log localized messages should create a logger using
     * {@link #getLogger(java.lang.String)} and then use the log methods that
     * take a resource bundle as parameter.
     *
     * @param name    the name of the logger.
     * @param bundle  a resource bundle.
     * @return an instance of {@link Logger} which will use the provided
     * resource bundle for message localization.
     * @throws NullPointerException if {@code name} is {@code null} or
     *         {@code bundle} is {@code null}.
     * @throws IllegalCallerException if there is no Java caller frame on the
     *         stack.
     *
     * @since 9
     */
    @CallerSensitive
    public static Logger getLogger(String name, ResourceBundle bundle) {
        final ResourceBundle rb = Objects.requireNonNull(bundle);
        Objects.requireNonNull(name);
        final Class<?> caller = Reflection.getCallerClass();
        if (caller == null) {
            throw new IllegalCallerException("no caller frame");
        }
        return LoggerFinder.accessProvider()
                .getLocalizedLogger(name, rb, caller.getModule());
    }

    /**
     * Initiates the {@linkplain Runtime##shutdown shutdown sequence} of the Java Virtual
     * Machine. This method initiates the shutdown sequence (if it is not already initiated)
     * and then blocks indefinitely. This method neither returns nor throws an exception;
     * that is, it does not complete either normally or abruptly.
     * <p>
     * The argument serves as a status code. By convention, a nonzero status code
     * indicates abnormal termination.
     * <p>
     * The call {@code System.exit(n)} is effectively equivalent to the call:
     * {@snippet :
     *     Runtime.getRuntime().exit(n)
     * }
     *
     * @implNote
     * The initiation of the shutdown sequence is logged by {@link Runtime#exit(int)}.
     *
     * @param  status exit status.
     * @see    java.lang.Runtime#exit(int)
     */
    public static void exit(int status) {
        Runtime.getRuntime().exit(status);
    }

    /**
     * Runs the garbage collector in the Java Virtual Machine.
     * <p>
     * Calling the {@code gc} method suggests that the Java Virtual Machine
     * expend effort toward recycling unused objects in order to
     * make the memory they currently occupy available for reuse
     * by the Java Virtual Machine.
     * When control returns from the method call, the Java Virtual Machine
     * has made a best effort to reclaim space from all unused objects.
     * There is no guarantee that this effort will recycle any particular
     * number of unused objects, reclaim any particular amount of space, or
     * complete at any particular time, if at all, before the method returns or ever.
     * There is also no guarantee that this effort will determine
     * the change of reachability in any particular number of objects,
     * or that any particular number of {@link java.lang.ref.Reference Reference}
     * objects will be cleared and enqueued.
     *
     * <p>
     * The call {@code System.gc()} is effectively equivalent to the
     * call:
     * <blockquote><pre>
     * Runtime.getRuntime().gc()
     * </pre></blockquote>
     *
     * @see     java.lang.Runtime#gc()
     */
    public static void gc() {
        Runtime.getRuntime().gc();
    }

    /**
     * Runs the finalization methods of any objects pending finalization.
     *
     * Calling this method suggests that the Java Virtual Machine expend
     * effort toward running the {@code finalize} methods of objects
     * that have been found to be discarded but whose {@code finalize}
     * methods have not yet been run. When control returns from the
     * method call, the Java Virtual Machine has made a best effort to
     * complete all outstanding finalizations.
     * <p>
     * The call {@code System.runFinalization()} is effectively
     * equivalent to the call:
     * <blockquote><pre>
     * Runtime.getRuntime().runFinalization()
     * </pre></blockquote>
     *
     * @deprecated Finalization has been deprecated for removal.  See
     * {@link java.lang.Object#finalize} for background information and details
     * about migration options.
     * <p>
     * When running in a JVM in which finalization has been disabled or removed,
     * no objects will be pending finalization, so this method does nothing.
     *
     * @see     java.lang.Runtime#runFinalization()
     * @jls 12.6 Finalization of Class Instances
     */
    @Deprecated(since="18", forRemoval=true)
    @SuppressWarnings("removal")
    public static void runFinalization() {
        Runtime.getRuntime().runFinalization();
    }

    /**
     * Loads the native library specified by the filename argument.  The filename
     * argument must be an absolute path name.
     *
     * If the filename argument, when stripped of any platform-specific library
     * prefix, path, and file extension, indicates a library whose name is,
     * for example, L, and a native library called L is statically linked
     * with the VM, then the JNI_OnLoad_L function exported by the library
     * is invoked rather than attempting to load a dynamic library.
     * A filename matching the argument does not have to exist in the
     * file system.
     * See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
     * for more details.
     *
     * Otherwise, the filename argument is mapped to a native library image in
     * an implementation-dependent manner.
     *
     * <p>
     * The call {@code System.load(name)} is effectively equivalent
     * to the call:
     * <blockquote><pre>
     * Runtime.getRuntime().load(name)
     * </pre></blockquote>
     *
     * @param      filename   the file to load.
     * @throws     UnsatisfiedLinkError  if either the filename is not an
     *             absolute path name, the native library is not statically
     *             linked with the VM, or the library cannot be mapped to
     *             a native library image by the host system.
     * @throws     NullPointerException if {@code filename} is {@code null}
     * @throws     IllegalCallerException if the caller is in a module that
     *             does not have native access enabled.
     *
     * @spec jni/index.html Java Native Interface Specification
     * @see        java.lang.Runtime#load(java.lang.String)
     */
    @CallerSensitive
    @Restricted
    public static void load(String filename) {
        Class<?> caller = Reflection.getCallerClass();
        Reflection.ensureNativeAccess(caller, System.class, "load", false);
        Runtime.getRuntime().load0(caller, filename);
    }

    /**
     * Loads the native library specified by the {@code libname}
     * argument.  The {@code libname} argument must not contain any platform
     * specific prefix, file extension or path. If a native library
     * called {@code libname} is statically linked with the VM, then the
     * JNI_OnLoad_{@code libname} function exported by the library is invoked.
     * See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
     * for more details.
     *
     * Otherwise, the libname argument is loaded from a system library
     * location and mapped to a native library image in an
     * implementation-dependent manner.
     * <p>
     * The call {@code System.loadLibrary(name)} is effectively
     * equivalent to the call
     * <blockquote><pre>
     * Runtime.getRuntime().loadLibrary(name)
     * </pre></blockquote>
     *
     * @param      libname   the name of the library.
     * @throws     UnsatisfiedLinkError if either the libname argument
     *             contains a file path, the native library is not statically
     *             linked with the VM,  or the library cannot be mapped to a
     *             native library image by the host system.
     * @throws     NullPointerException if {@code libname} is {@code null}
     * @throws     IllegalCallerException if the caller is in a module that
     *             does not have native access enabled.
     *
     * @spec jni/index.html Java Native Interface Specification
     * @see        java.lang.Runtime#loadLibrary(java.lang.String)
     */
    @CallerSensitive
    @Restricted
    public static void loadLibrary(String libname) {
        Class<?> caller = Reflection.getCallerClass();
        Reflection.ensureNativeAccess(caller, System.class, "loadLibrary", false);
        Runtime.getRuntime().loadLibrary0(caller, libname);
    }

    /**
     * Maps a library name into a platform-specific string representing
     * a native library.
     *
     * @param      libname the name of the library.
     * @return     a platform-dependent native library name.
     * @throws     NullPointerException if {@code libname} is {@code null}
     * @see        java.lang.System#loadLibrary(java.lang.String)
     * @see        java.lang.ClassLoader#findLibrary(java.lang.String)
     * @since      1.2
     */
    public static native String mapLibraryName(String libname);

    /**
     * Create PrintStream for stdout/err based on encoding.
     */
    private static PrintStream newPrintStream(OutputStream out, String enc) {
        if (enc != null) {
            return new PrintStream(new BufferedOutputStream(out, 128), true,
                                   Charset.forName(enc, UTF_8.INSTANCE));
        }
        return new PrintStream(new BufferedOutputStream(out, 128), true);
    }

    /**
     * Logs an exception/error at initialization time to stdout or stderr.
     *
     * @param printToStderr to print to stderr rather than stdout
     * @param printStackTrace to print the stack trace
     * @param msg the message to print before the exception, can be {@code null}
     * @param e the exception or error
     */
    private static void logInitException(boolean printToStderr,
                                         boolean printStackTrace,
                                         String msg,
                                         Throwable e) {
        if (VM.initLevel() < 1) {
            throw new InternalError("system classes not initialized");
        }
        PrintStream log = (printToStderr) ? err : out;
        if (msg != null) {
            log.println(msg);
        }
        if (printStackTrace) {
            e.printStackTrace(log);
        } else {
            log.println(e);
            for (Throwable suppressed : e.getSuppressed()) {
                log.println("Suppressed: " + suppressed);
            }
            Throwable cause = e.getCause();
            if (cause != null) {
                log.println("Caused by: " + cause);
            }
        }
    }

    /**
     * Create the Properties object from a map - masking out system properties
     * that are not intended for public access.
     */
    private static Properties createProperties(Map<String, String> initialProps) {
        Properties properties = new Properties(initialProps.size());
        for (var entry : initialProps.entrySet()) {
            String prop = entry.getKey();
            switch (prop) {
                // Do not add private system properties to the Properties
                case "sun.nio.MaxDirectMemorySize":
                case "sun.nio.PageAlignDirectMemory":
                    // used by java.lang.Integer.IntegerCache
                case "java.lang.Integer.IntegerCache.high":
                    // used by sun.launcher.LauncherHelper
                case "sun.java.launcher.diag":
                    // used by jdk.internal.loader.ClassLoaders
                case "jdk.boot.class.path.append":
                    break;
                default:
                    properties.put(prop, entry.getValue());
            }
        }
        return properties;
    }

    /**
     * Initialize the system class.  Called after thread initialization.
     */
    private static void initPhase1() {

        // register the shared secrets - do this first, since SystemProps.initProperties
        // might initialize CharsetDecoders that rely on it
        setJavaLangAccess();

        // VM might invoke JNU_NewStringPlatform() to set those encoding
        // sensitive properties (user.home, user.name, boot.class.path, etc.)
        // during "props" initialization.
        // The charset is initialized in System.c and does not depend on the Properties.
        Map<String, String> tempProps = SystemProps.initProperties();
        VersionProps.init(tempProps);

        // There are certain system configurations that may be controlled by
        // VM options such as the maximum amount of direct memory and
        // Integer cache size used to support the object identity semantics
        // of autoboxing.  Typically, the library will obtain these values
        // from the properties set by the VM.  If the properties are for
        // internal implementation use only, these properties should be
        // masked from the system properties.
        //
        // Save a private copy of the system properties object that
        // can only be accessed by the internal implementation.
        VM.saveProperties(tempProps);
        props = createProperties(tempProps);

        // Check if sun.jnu.encoding is supported. If not, replace it with UTF-8.
        var jnuEncoding = props.getProperty("sun.jnu.encoding");
        if (jnuEncoding == null || !Charset.isSupported(jnuEncoding)) {
            notSupportedJnuEncoding = jnuEncoding == null ? "null" : jnuEncoding;
            props.setProperty("sun.jnu.encoding", "UTF-8");
        }

        StaticProperty.javaHome();          // Load StaticProperty to cache the property values

        lineSeparator = props.getProperty("line.separator");

        FileInputStream fdIn = new In(FileDescriptor.in);
        FileOutputStream fdOut = new Out(FileDescriptor.out);
        FileOutputStream fdErr = new Out(FileDescriptor.err);
        initialIn = new BufferedInputStream(fdIn);
        setIn0(initialIn);
        // stdout/err.encoding are set when the VM is associated with the terminal,
        // thus they are equivalent to Console.charset(), otherwise the encodings
        // of those properties default to native.encoding
        setOut0(newPrintStream(fdOut, props.getProperty("stdout.encoding")));
        initialErr = newPrintStream(fdErr, props.getProperty("stderr.encoding"));
        setErr0(initialErr);

        // Setup Java signal handlers for HUP, TERM, and INT (where available).
        Terminator.setup();

        // Initialize any miscellaneous operating system settings that need to be
        // set for the class libraries. Currently this is no-op everywhere except
        // for Windows where the process-wide error mode is set before the java.io
        // classes are used.
        VM.initializeOSEnvironment();

        // start Finalizer and Reference Handler threads
        SharedSecrets.getJavaLangRefAccess().startThreads();

        // system properties, java.lang and other core classes are now initialized
        VM.initLevel(1);
    }

    /**
     * System.in.
     */
    private static class In extends FileInputStream {
        In(FileDescriptor fd) {
            super(fd);
        }

        @Override
        public int read() throws IOException {
            boolean attempted = Blocker.begin();
            try {
                return super.read();
            } finally {
                Blocker.end(attempted);
            }
        }

        @Override
        public int read(byte[] b) throws IOException {
            boolean attempted = Blocker.begin();
            try {
                return super.read(b);
            } finally {
                Blocker.end(attempted);
            }
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            boolean attempted = Blocker.begin();
            try {
                return super.read(b, off, len);
            } finally {
                Blocker.end(attempted);
            }
        }
    }

    /**
     * System.out/System.err wrap this output stream.
     */
    private static class Out extends FileOutputStream {
        Out(FileDescriptor fd) {
            super(fd);
        }

        @Override
        public void write(int b) throws IOException {
            boolean attempted = Blocker.begin();
            try {
                super.write(b);
            } finally {
                Blocker.end(attempted);
            }
        }

        @Override
        public void write(byte[] b) throws IOException {
            boolean attempted = Blocker.begin();
            try {
                super.write(b);
            } finally {
                Blocker.end(attempted);
            }
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            boolean attempted = Blocker.begin();
            try {
                super.write(b, off, len);
            } finally {
                Blocker.end(attempted);
            }
        }
    }

    // @see #initPhase2()
    static ModuleLayer bootLayer;

    /*
     * Invoked by VM.  Phase 2 module system initialization.
     * Only classes in java.base can be loaded in this phase.
     *
     * @param printToStderr print exceptions to stderr rather than stdout
     * @param printStackTrace print stack trace when exception occurs
     *
     * @return JNI_OK for success, JNI_ERR for failure
     */
    private static int initPhase2(boolean printToStderr, boolean printStackTrace) {

        try {
            bootLayer = ModuleBootstrap.boot();
        } catch (Exception | Error e) {
            logInitException(printToStderr, printStackTrace,
                             "Error occurred during initialization of boot layer", e);
            return -1; // JNI_ERR
        }

        // module system initialized
        VM.initLevel(2);

        return 0; // JNI_OK
    }

    /*
     * Invoked by VM.  Phase 3 is the final system initialization:
     * 1. set system class loader
     * 2. set TCCL
     *
     * This method must be called after the module system initialization.
     */
    private static void initPhase3() {

        // Emit a warning if java.io.tmpdir is set via the command line
        // to a directory that doesn't exist
        if (SystemProps.isBadIoTmpdir()) {
            System.err.println("WARNING: java.io.tmpdir directory does not exist");
        }

        String smProp = System.getProperty("java.security.manager");
        if (smProp != null) {
            switch (smProp) {
                case "disallow":
                    break;
                case "allow":
                case "":
                case "default":
                default:
                    throw new Error("A command line option has attempted to allow or enable the Security Manager."
                            + " Enabling a Security Manager is not supported.");
            }
        }

        // Emit a warning if `sun.jnu.encoding` is not supported.
        if (notSupportedJnuEncoding != null) {
            System.err.println(
                    "WARNING: The encoding of the underlying platform's" +
                    " file system is not supported: " +
                    notSupportedJnuEncoding);
        }

        // initializing the system class loader
        VM.initLevel(3);

        // system class loader initialized
        ClassLoader scl = ClassLoader.initSystemClassLoader();

        // set TCCL
        Thread.currentThread().setContextClassLoader(scl);

        // system is fully initialized
        VM.initLevel(4);
    }

    private static void setJavaLangAccess() {
        // Allow privileged classes outside of java.lang
        SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
            public List<Method> getDeclaredPublicMethods(Class<?> klass, String name, Class<?>... parameterTypes) {
                return klass.getDeclaredPublicMethods(name, parameterTypes);
            }
            public Method findMethod(Class<?> klass, boolean publicOnly, String name, Class<?>... parameterTypes) {
                return klass.findMethod(publicOnly, name, parameterTypes);
            }
            public jdk.internal.reflect.ConstantPool getConstantPool(Class<?> klass) {
                return klass.getConstantPool();
            }
            public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
                return klass.casAnnotationType(oldType, newType);
            }
            public AnnotationType getAnnotationType(Class<?> klass) {
                return klass.getAnnotationType();
            }
            public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) {
                return klass.getDeclaredAnnotationMap();
            }
            public byte[] getRawClassAnnotations(Class<?> klass) {
                return klass.getRawAnnotations();
            }
            public byte[] getRawClassTypeAnnotations(Class<?> klass) {
                return klass.getRawTypeAnnotations();
            }
            public byte[] getRawExecutableTypeAnnotations(Executable executable) {
                return Class.getExecutableTypeAnnotationBytes(executable);
            }
            public <E extends Enum<E>>
            E[] getEnumConstantsShared(Class<E> klass) {
                return klass.getEnumConstantsShared();
            }
            public int classFileVersion(Class<?> clazz) {
                return clazz.getClassFileVersion();
            }
            public void blockedOn(Interruptible b) {
                Thread.currentThread().blockedOn(b);
            }
            public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
                Shutdown.add(slot, registerShutdownInProgress, hook);
            }
            @SuppressWarnings("removal")
            public void invokeFinalize(Object o) throws Throwable {
                o.finalize();
            }
            public ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl) {
                return cl.createOrGetClassLoaderValueMap();
            }
            public Class<?> defineClass(ClassLoader loader, String name, byte[] b, ProtectionDomain pd, String source) {
                return ClassLoader.defineClass1(loader, name, b, 0, b.length, pd, source);
            }
            public Class<?> defineClass(ClassLoader loader, Class<?> lookup, String name, byte[] b, ProtectionDomain pd,
                                        boolean initialize, int flags, Object classData) {
                return ClassLoader.defineClass0(loader, lookup, name, b, 0, b.length, pd, initialize, flags, classData);
            }
            public Class<?> findBootstrapClassOrNull(String name) {
                return ClassLoader.findBootstrapClassOrNull(name);
            }
            public Package definePackage(ClassLoader cl, String name, Module module) {
                return cl.definePackage(name, module);
            }
            public Module defineModule(ClassLoader loader,
                                       ModuleDescriptor descriptor,
                                       URI uri) {
                return new Module(null, loader, descriptor, uri);
            }
            public Module defineUnnamedModule(ClassLoader loader) {
                return new Module(loader);
            }
            public void addReads(Module m1, Module m2) {
                m1.implAddReads(m2);
            }
            public void addReadsAllUnnamed(Module m) {
                m.implAddReadsAllUnnamed();
            }
            public void addExports(Module m, String pn) {
                m.implAddExports(pn);
            }
            public void addExports(Module m, String pn, Module other) {
                m.implAddExports(pn, other);
            }
            public void addExportsToAllUnnamed(Module m, String pn) {
                m.implAddExportsToAllUnnamed(pn);
            }
            public void addOpens(Module m, String pn, Module other) {
                m.implAddOpens(pn, other);
            }
            public void addOpensToAllUnnamed(Module m, String pn) {
                m.implAddOpensToAllUnnamed(pn);
            }
            public void addUses(Module m, Class<?> service) {
                m.implAddUses(service);
            }
            public boolean isReflectivelyExported(Module m, String pn, Module other) {
                return m.isReflectivelyExported(pn, other);
            }
            public boolean isReflectivelyOpened(Module m, String pn, Module other) {
                return m.isReflectivelyOpened(pn, other);
            }
            public Module addEnableNativeAccess(Module m) {
                return m.implAddEnableNativeAccess();
            }
            public boolean addEnableNativeAccess(ModuleLayer layer, String name) {
                return layer.addEnableNativeAccess(name);
            }
            public void addEnableNativeAccessToAllUnnamed() {
                Module.implAddEnableNativeAccessToAllUnnamed();
            }
            public void ensureNativeAccess(Module m, Class<?> owner, String methodName, Class<?> currentClass, boolean jni) {
                m.ensureNativeAccess(owner, methodName, currentClass, jni);
            }
            public ServicesCatalog getServicesCatalog(ModuleLayer layer) {
                return layer.getServicesCatalog();
            }
            public void bindToLoader(ModuleLayer layer, ClassLoader loader) {
                layer.bindToLoader(loader);
            }
            public Stream<ModuleLayer> layers(ModuleLayer layer) {
                return layer.layers();
            }
            public Stream<ModuleLayer> layers(ClassLoader loader) {
                return ModuleLayer.layers(loader);
            }

            public int uncheckedCountPositives(byte[] bytes, int offset, int length) {
                return StringCoding.countPositives(bytes, offset, length);
            }
            public int countNonZeroAscii(String s) {
                return StringCoding.countNonZeroAscii(s);
            }
            public String uncheckedNewStringNoRepl(byte[] bytes, Charset cs) throws CharacterCodingException  {
                return String.newStringNoRepl(bytes, cs);
            }
            public char uncheckedGetUTF16Char(byte[] bytes, int index) {
                return StringUTF16.getChar(bytes, index);
            }
            public void uncheckedPutCharUTF16(byte[] bytes, int index, int ch) {
                StringUTF16.putChar(bytes, index, ch);
            }
            public byte[] uncheckedGetBytesNoRepl(String s, Charset cs) throws CharacterCodingException {
                return String.getBytesNoRepl(s, cs);
            }

            public String newStringUTF8NoRepl(byte[] bytes, int off, int len) {
                return String.newStringUTF8NoRepl(bytes, off, len, true);
            }

            public byte[] getBytesUTF8NoRepl(String s) {
                return String.getBytesUTF8NoRepl(s);
            }

            public void uncheckedInflateBytesToChars(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
                StringLatin1.inflate(src, srcOff, dst, dstOff, len);
            }

            public int uncheckedDecodeASCII(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
                return String.decodeASCII(src, srcOff, dst, dstOff, len);
            }

            public int uncheckedEncodeASCII(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
                return StringCoding.implEncodeAsciiArray(src, srcOff, dst, dstOff, len);
            }

            public InputStream initialSystemIn() {
                return initialIn;
            }

            public PrintStream initialSystemErr() {
                return initialErr;
            }

            public void setCause(Throwable t, Throwable cause) {
                t.setCause(cause);
            }

            public ProtectionDomain protectionDomain(Class<?> c) {
                return c.getProtectionDomain();
            }

            public MethodHandle stringConcatHelper(String name, MethodType methodType) {
                return StringConcatHelper.lookupStatic(name, methodType);
            }

            public long stringConcatInitialCoder() {
                return StringConcatHelper.initialCoder();
            }

            public long stringConcatMix(long lengthCoder, String constant) {
                return StringConcatHelper.mix(lengthCoder, constant);
            }

            public long stringConcatMix(long lengthCoder, char value) {
                return StringConcatHelper.mix(lengthCoder, value);
            }

            public Object uncheckedStringConcat1(String[] constants) {
                return new StringConcatHelper.Concat1(constants);
            }

            public byte stringInitCoder() {
                return String.COMPACT_STRINGS ? String.LATIN1 : String.UTF16;
            }

            public byte stringCoder(String str) {
                return str.coder();
            }

            public String join(String prefix, String suffix, String delimiter, String[] elements, int size) {
                return String.join(prefix, suffix, delimiter, elements, size);
            }

            public String concat(String prefix, Object value, String suffix) {
                return StringConcatHelper.concat(prefix, value, suffix);
            }

            public Object classData(Class<?> c) {
                return c.getClassData();
            }

            @Override
            public NativeLibraries nativeLibrariesFor(ClassLoader loader) {
                return ClassLoader.nativeLibrariesFor(loader);
            }

            public Thread[] getAllThreads() {
                return Thread.getAllThreads();
            }

            public ThreadContainer threadContainer(Thread thread) {
                return thread.threadContainer();
            }

            public void start(Thread thread, ThreadContainer container) {
                thread.start(container);
            }

            public StackableScope headStackableScope(Thread thread) {
                return thread.headStackableScopes();
            }

            public void setHeadStackableScope(StackableScope scope) {
                Thread.setHeadStackableScope(scope);
            }

            public Thread currentCarrierThread() {
                return Thread.currentCarrierThread();
            }

            public <T> T getCarrierThreadLocal(CarrierThreadLocal<T> local) {
                return ((ThreadLocal<T>)local).getCarrierThreadLocal();
            }

            public <T> void setCarrierThreadLocal(CarrierThreadLocal<T> local, T value) {
                ((ThreadLocal<T>)local).setCarrierThreadLocal(value);
            }

            public void removeCarrierThreadLocal(CarrierThreadLocal<?> local) {
                ((ThreadLocal<?>)local).removeCarrierThreadLocal();
            }

            public Object[] scopedValueCache() {
                return Thread.scopedValueCache();
            }

            public void setScopedValueCache(Object[] cache) {
                Thread.setScopedValueCache(cache);
            }

            public Object scopedValueBindings() {
                return Thread.scopedValueBindings();
            }

            public Continuation getContinuation(Thread thread) {
                return thread.getContinuation();
            }

            public void setContinuation(Thread thread, Continuation continuation) {
                thread.setContinuation(continuation);
            }

            public ContinuationScope virtualThreadContinuationScope() {
                return VirtualThread.continuationScope();
            }

            public void parkVirtualThread() {
                Thread thread = Thread.currentThread();
                if (thread instanceof BaseVirtualThread vthread) {
                    vthread.park();
                } else {
                    throw new WrongThreadException();
                }
            }

            public void parkVirtualThread(long nanos) {
                Thread thread = Thread.currentThread();
                if (thread instanceof BaseVirtualThread vthread) {
                    vthread.parkNanos(nanos);
                } else {
                    throw new WrongThreadException();
                }
            }

            public void unparkVirtualThread(Thread thread) {
                if (thread instanceof BaseVirtualThread vthread) {
                    vthread.unpark();
                } else {
                    throw new WrongThreadException();
                }
            }

            public Executor virtualThreadDefaultScheduler() {
                return VirtualThread.defaultScheduler();
            }

            public StackWalker newStackWalkerInstance(Set<StackWalker.Option> options,
                                                      ContinuationScope contScope,
                                                      Continuation continuation) {
                return StackWalker.newInstance(options, null, contScope, continuation);
            }

            public String getLoaderNameID(ClassLoader loader) {
                return loader != null ? loader.nameAndId() : "null";
            }

            @Override
            public void copyToSegmentRaw(String string, MemorySegment segment, long offset) {
                string.copyToSegmentRaw(segment, offset);
            }

            @Override
            public boolean bytesCompatible(String string, Charset charset) {
                return string.bytesCompatible(charset);
            }
        });
    }
}
