       1 /*
       2  * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
       3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4  *
       5  * This code is free software; you can redistribute it and/or modify it
       6  * under the terms of the GNU General Public License version 2 only, as
       7  * published by the Free Software Foundation.  Oracle designates this
       8  * particular file as subject to the "Classpath" exception as provided
       9  * by Oracle in the LICENSE file that accompanied this code.
      10  *
      11  * This code is distributed in the hope that it will be useful, but WITHOUT
      12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14  * version 2 for more details (a copy is included in the LICENSE file that
      15  * accompanied this code).
      16  *
      17  * You should have received a copy of the GNU General Public License version
      18  * 2 along with this work; if not, write to the Free Software Foundation,
      19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
      20  *
      21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
      22  * or visit www.oracle.com if you need additional information or have any
      23  * questions.
      24  */
      25 package java.lang;
      26
      27 import java.io.BufferedInputStream;
      28 import java.io.BufferedOutputStream;
      29 import java.io.Console;
      30 import java.io.FileDescriptor;
      31 import java.io.FileInputStream;
      32 import java.io.FileOutputStream;
      33 import java.io.IOException;
      34 import java.io.InputStream;
      35 import java.io.PrintStream;
      36 import java.io.UnsupportedEncodingException;
      37 import java.lang.annotation.Annotation;
      38 import java.lang.invoke.MethodHandle;
      39 import java.lang.invoke.MethodType;
      40 import java.lang.invoke.StringConcatFactory;
      41 import java.lang.module.ModuleDescriptor;
      42 import java.lang.reflect.Constructor;
      43 import java.lang.reflect.Executable;
      44 import java.lang.reflect.Method;
      45 import java.lang.reflect.Modifier;
      46 import java.net.URI;
      47 import java.nio.charset.CharacterCodingException;
      48 import java.security.AccessControlContext;
      49 import java.security.ProtectionDomain;
      50 import java.security.AccessController;
      51 import java.security.PrivilegedAction;
      52 import java.nio.channels.Channel;
      53 import java.nio.channels.spi.SelectorProvider;
      54 import java.nio.charset.Charset;
      55 import java.util.List;
      56 import java.util.Map;
      57 import java.util.Objects;
      58 import java.util.Properties;
      59 import java.util.PropertyPermission;
      60 import java.util.ResourceBundle;
      61 import java.util.Set;
      62 import java.util.function.Supplier;
      63 import java.util.concurrent.ConcurrentHashMap;
      64 import java.util.stream.Stream;
      65
      66 import jdk.internal.misc.Unsafe;
      67 import jdk.internal.util.StaticProperty;
      68 import jdk.internal.module.ModuleBootstrap;
      69 import jdk.internal.module.ServicesCatalog;
      70 import jdk.internal.reflect.CallerSensitive;
      71 import jdk.internal.reflect.Reflection;
      72 import jdk.internal.access.JavaLangAccess;
      73 import jdk.internal.access.SharedSecrets;
      74 import jdk.internal.misc.VM;
      75 import jdk.internal.logger.LoggerFinderLoader;
      76 import jdk.internal.logger.LazyLoggers;
      77 import jdk.internal.logger.LocalizedLoggerWrapper;
      78 import jdk.internal.util.SystemProps;
      79 import jdk.internal.vm.annotation.IntrinsicCandidate;
      80 import jdk.internal.vm.annotation.Stable;
      81 import sun.nio.fs.DefaultFileSystemProvider;
      82 import sun.reflect.annotation.AnnotationType;
      83 import sun.nio.ch.Interruptible;
      84 import sun.security.util.SecurityConstants;
      85
      86 /**
      87  * The {@code System} class contains several useful class fields
      88  * and methods. It cannot be instantiated.
      89  *
      90  * Among the facilities provided by the {@code System} class
      91  * are standard input, standard output, and error output streams;
      92  * access to externally defined properties and environment
      93  * variables; a means of loading files and libraries; and a utility
      94  * method for quickly copying a portion of an array.
      95  *
      96  * @since   1.0
      97  */
      98 public final class System {
      99     /* Register the natives via the static initializer.
     100      *
     101      * The VM will invoke the initPhase1 method to complete the initialization
     102      * of this class separate from <clinit>.
     103      */
     104     private static native void registerNatives();
     105     static {
     106         registerNatives();
     107     }
     108
     109     /** Don't let anyone instantiate this class */
     110     private System() {
     111     }
     112
     113     /**
     114      * The "standard" input stream. This stream is already
     115      * open and ready to supply input data. Typically this stream
     116      * corresponds to keyboard input or another input source specified by
     117      * the host environment or user. In case this stream is wrapped
     118      * in a {@link java.io.InputStreamReader}, {@link Console#charset()}
     119      * should be used for the charset, or consider using
     120      * {@link Console#reader()}.
     121      *
     122      * @see Console#charset()
     123      * @see Console#reader()
     124      */
     125     public static final InputStream in = null;
     126
     127     /**
     128      * The "standard" output stream. This stream is already
     129      * open and ready to accept output data. Typically this stream
     130      * corresponds to display output or another output destination
     131      * specified by the host environment or user. The encoding used
     132      * in the conversion from characters to bytes is equivalent to
     133      * {@link Console#charset()} if the {@code Console} exists,
     134      * {@link Charset#defaultCharset()} otherwise.
     135      * <p>
     136      * For simple stand-alone Java applications, a typical way to write
     137      * a line of output data is:
     138      * <blockquote><pre>
     139      *     System.out.println(data)
     140      * </pre></blockquote>
     141      * <p>
     142      * See the {@code println} methods in class {@code PrintStream}.
     143      *
     144      * @see     java.io.PrintStream#println()
     145      * @see     java.io.PrintStream#println(boolean)
     146      * @see     java.io.PrintStream#println(char)
     147      * @see     java.io.PrintStream#println(char[])
     148      * @see     java.io.PrintStream#println(double)
     149      * @see     java.io.PrintStream#println(float)
     150      * @see     java.io.PrintStream#println(int)
     151      * @see     java.io.PrintStream#println(long)
     152      * @see     java.io.PrintStream#println(java.lang.Object)
     153      * @see     java.io.PrintStream#println(java.lang.String)
     154      * @see     Console#charset()
     155      * @see     Charset#defaultCharset()
     156      */
     157     public static final PrintStream out = null;
     158
     159     /**
     160      * The "standard" error output stream. This stream is already
     161      * open and ready to accept output data.
     162      * <p>
     163      * Typically this stream corresponds to display output or another
     164      * output destination specified by the host environment or user. By
     165      * convention, this output stream is used to display error messages
     166      * or other information that should come to the immediate attention
     167      * of a user even if the principal output stream, the value of the
     168      * variable {@code out}, has been redirected to a file or other
     169      * destination that is typically not continuously monitored.
     170      * The encoding used in the conversion from characters to bytes is
     171      * equivalent to {@link Console#charset()} if the {@code Console}
     172      * exists, {@link Charset#defaultCharset()} otherwise.
     173      *
     174      * @see     Console#charset()
     175      * @see     Charset#defaultCharset()
     176      */
     177     public static final PrintStream err = null;
     178
     179     // indicates if a security manager is possible
     180     private static final int NEVER = 1;
     181     private static final int MAYBE = 2;
     182     private static @Stable int allowSecurityManager;
     183
     184     // current security manager
     185     private static volatile SecurityManager security;   // read by VM
     186
     187     // return true if a security manager is allowed
     188     private static boolean allowSecurityManager() {
     189         return (allowSecurityManager != NEVER);
     190     }
     191
     192     /**
     193      * Reassigns the "standard" input stream.
     194      *
     195      * First, if there is a security manager, its {@code checkPermission}
     196      * method is called with a {@code RuntimePermission("setIO")} permission
     197      *  to see if it's ok to reassign the "standard" input stream.
     198      *
     199      * @param in the new standard input stream.
     200      *
     201      * @throws SecurityException
     202      *        if a security manager exists and its
     203      *        {@code checkPermission} method doesn't allow
     204      *        reassigning of the standard input stream.
     205      *
     206      * @see SecurityManager#checkPermission
     207      * @see java.lang.RuntimePermission
     208      *
     209      * @since   1.1
     210      */
     211     public static void setIn(InputStream in) {
     212         checkIO();
     213         setIn0(in);
     214     }
     215
     216     /**
     217      * Reassigns the "standard" output stream.
     218      *
     219      * First, if there is a security manager, its {@code checkPermission}
     220      * method is called with a {@code RuntimePermission("setIO")} permission
     221      *  to see if it's ok to reassign the "standard" output stream.
     222      *
     223      * @param out the new standard output stream
     224      *
     225      * @throws SecurityException
     226      *        if a security manager exists and its
     227      *        {@code checkPermission} method doesn't allow
     228      *        reassigning of the standard output stream.
     229      *
     230      * @see SecurityManager#checkPermission
     231      * @see java.lang.RuntimePermission
     232      *
     233      * @since   1.1
     234      */
     235     public static void setOut(PrintStream out) {
     236         checkIO();
     237         setOut0(out);
     238     }
     239
     240     /**
     241      * Reassigns the "standard" error output stream.
     242      *
     243      * First, if there is a security manager, its {@code checkPermission}
     244      * method is called with a {@code RuntimePermission("setIO")} permission
     245      *  to see if it's ok to reassign the "standard" error output stream.
     246      *
     247      * @param err the new standard error output stream.
     248      *
     249      * @throws SecurityException
     250      *        if a security manager exists and its
     251      *        {@code checkPermission} method doesn't allow
     252      *        reassigning of the standard error output stream.
     253      *
     254      * @see SecurityManager#checkPermission
     255      * @see java.lang.RuntimePermission
     256      *
     257      * @since   1.1
     258      */
     259     public static void setErr(PrintStream err) {
     260         checkIO();
     261         setErr0(err);
     262     }
     263
     264     private static volatile Console cons;
     265
     266     /**
     267      * Returns the unique {@link java.io.Console Console} object associated
     268      * with the current Java virtual machine, if any.
     269      *
     270      * @return  The system console, if any, otherwise {@code null}.
     271      *
     272      * @since   1.6
     273      */
     274      public static Console console() {
     275          Console c;
     276          if ((c = cons) == null) {
     277              synchronized (System.class) {
     278                  if ((c = cons) == null) {
     279                      cons = c = SharedSecrets.getJavaIOAccess().console();
     280                  }
     281              }
     282          }
     283          return c;
     284      }
     285
     286     /**
     287      * Returns the channel inherited from the entity that created this
     288      * Java virtual machine.
     289      *
     290      * This method returns the channel obtained by invoking the
     291      * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel
     292      * inheritedChannel} method of the system-wide default
     293      * {@link java.nio.channels.spi.SelectorProvider} object.
     294      *
     295      * <p> In addition to the network-oriented channels described in
     296      * {@link java.nio.channels.spi.SelectorProvider#inheritedChannel
     297      * inheritedChannel}, this method may return other kinds of
     298      * channels in the future.
     299      *
     300      * @return  The inherited channel, if any, otherwise {@code null}.
     301      *
     302      * @throws  IOException
     303      *          If an I/O error occurs
     304      *
     305      * @throws  SecurityException
     306      *          If a security manager is present and it does not
     307      *          permit access to the channel.
     308      *
     309      * @since 1.5
     310      */
     311     public static Channel inheritedChannel() throws IOException {
     312         return SelectorProvider.provider().inheritedChannel();
     313     }
     314
     315     private static void checkIO() {
     316         SecurityManager sm = getSecurityManager();
     317         if (sm != null) {
     318             sm.checkPermission(new RuntimePermission("setIO"));
     319         }
     320     }
     321
     322     private static native void setIn0(InputStream in);
     323     private static native void setOut0(PrintStream out);
     324     private static native void setErr0(PrintStream err);
     325
     326     /**
     327      * Sets the system-wide security manager.
     328      *
     329      * If there is a security manager already installed, this method first
     330      * calls the security manager's {@code checkPermission} method
     331      * with a {@code RuntimePermission("setSecurityManager")}
     332      * permission to ensure it's ok to replace the existing
     333      * security manager.
     334      * This may result in throwing a {@code SecurityException}.
     335      *
     336      * <p> Otherwise, the argument is established as the current
     337      * security manager. If the argument is {@code null} and no
     338      * security manager has been established, then no action is taken and
     339      * the method simply returns.
     340      *
     341      * @implNote In the JDK implementation, if the Java virtual machine is
     342      * started with the system property {@code java.security.manager} set to
     343      * the special token "{@code disallow}" then the {@code setSecurityManager}
     344      * method cannot be used to set a security manager.
     345      *
     346      * @param  sm the security manager or {@code null}
     347      * @throws SecurityException
     348      *         if the security manager has already been set and its {@code
     349      *         checkPermission} method doesn't allow it to be replaced
     350      * @throws UnsupportedOperationException
     351      *         if {@code sm} is non-null and a security manager is not allowed
     352      *         to be set dynamically
     353      * @see #getSecurityManager
     354      * @see SecurityManager#checkPermission
     355      * @see java.lang.RuntimePermission

     356      */

     357     public static void setSecurityManager(SecurityManager sm) {
     358         if (allowSecurityManager()) {
     359             if (security == null) {
     360                 // ensure image reader is initialized
     361                 Object.class.getResource("java/lang/ANY");
     362                 // ensure the default file system is initialized
     363                 DefaultFileSystemProvider.theFileSystem();
     364             }
     365             if (sm != null) {
     366                 try {
     367                     // pre-populates the SecurityManager.packageAccess cache
     368                     // to avoid recursive permission checking issues with custom
     369                     // SecurityManager implementations
     370                     sm.checkPackageAccess("java.lang");
     371                 } catch (Exception e) {
     372                     // no-op
     373                 }
     374             }
     375             setSecurityManager0(sm);
     376         } else {
     377             // security manager not allowed
     378             if (sm != null) {
     379                 throw new UnsupportedOperationException(
     380                     "Runtime configured to disallow security manager");
     381             }
     382         }
     383     }
     384
     385     private static synchronized
     386     void setSecurityManager0(final SecurityManager s) {
     387         SecurityManager sm = getSecurityManager();
     388         if (sm != null) {
     389             // ask the currently installed security manager if we
     390             // can replace it.
     391             sm.checkPermission(new RuntimePermission("setSecurityManager"));
     392         }
     393
     394         if ((s != null) && (s.getClass().getClassLoader() != null)) {
     395             // New security manager class is not on bootstrap classpath.
     396             // Force policy to get initialized before we install the new
     397             // security manager, in order to prevent infinite loops when
     398             // trying to initialize the policy (which usually involves
     399             // accessing some security and/or system properties, which in turn
     400             // calls the installed security manager's checkPermission method
     401             // which will loop infinitely if there is a non-system class
     402             // (in this case: the new security manager class) on the stack).
     403             AccessController.doPrivileged(new PrivilegedAction<>() {
     404                 public Object run() {
     405                     s.getClass().getProtectionDomain().implies
     406                         (SecurityConstants.ALL_PERMISSION);
     407                     return null;
     408                 }
     409             });
     410         }
     411
     412         security = s;
     413     }
     414
     415     /**
     416      * Gets the system-wide security manager.
     417      *
     418      * @return  if a security manager has already been established for the
     419      *          current application, then that security manager is returned;
     420      *          otherwise, {@code null} is returned.
     421      * @see     #setSecurityManager

     422      */

     423     public static SecurityManager getSecurityManager() {
     424         if (allowSecurityManager()) {
     425             return security;
     426         } else {
     427             return null;
     428         }
     429     }
     430
     431     /**
     432      * Returns the current time in milliseconds.  Note that
     433      * while the unit of time of the return value is a millisecond,
     434      * the granularity of the value depends on the underlying
     435      * operating system and may be larger.  For example, many
     436      * operating systems measure time in units of tens of
     437      * milliseconds.
     438      *
     439      * <p> See the description of the class {@code Date} for
     440      * a discussion of slight discrepancies that may arise between
     441      * "computer time" and coordinated universal time (UTC).
     442      *
     443      * @return  the difference, measured in milliseconds, between
     444      *          the current time and midnight, January 1, 1970 UTC.
     445      * @see     java.util.Date
     446      */
     447     @IntrinsicCandidate
     448     public static native long currentTimeMillis();
     449
     450     /**
     451      * Returns the current value of the running Java Virtual Machine's
     452      * high-resolution time source, in nanoseconds.
     453      *
     454      * This method can only be used to measure elapsed time and is
     455      * not related to any other notion of system or wall-clock time.
     456      * The value returned represents nanoseconds since some fixed but
     457      * arbitrary <i>origin</i> time (perhaps in the future, so values
     458      * may be negative).  The same origin is used by all invocations of
     459      * this method in an instance of a Java virtual machine; other
     460      * virtual machine instances are likely to use a different origin.
     461      *
     462      * <p>This method provides nanosecond precision, but not necessarily
     463      * nanosecond resolution (that is, how frequently the value changes)
     464      * - no guarantees are made except that the resolution is at least as
     465      * good as that of {@link #currentTimeMillis()}.
     466      *
     467      * <p>Differences in successive calls that span greater than
     468      * approximately 292 years (2<sup>63</sup> nanoseconds) will not
     469      * correctly compute elapsed time due to numerical overflow.
     470      *
     471      * <p>The values returned by this method become meaningful only when
     472      * the difference between two such values, obtained within the same
     473      * instance of a Java virtual machine, is computed.
     474      *
     475      * <p>For example, to measure how long some code takes to execute:
     476      * <pre> {@code
     477      * long startTime = System.nanoTime();
     478      * // ... the code being measured ...
     479      * long elapsedNanos = System.nanoTime() - startTime;}</pre>
     480      *
     481      * <p>To compare elapsed time against a timeout, use <pre> {@code
     482      * if (System.nanoTime() - startTime >= timeoutNanos) ...}</pre>
     483      * instead of <pre> {@code
     484      * if (System.nanoTime() >= startTime + timeoutNanos) ...}</pre>
     485      * because of the possibility of numerical overflow.
     486      *
     487      * @return the current value of the running Java Virtual Machine's
     488      *         high-resolution time source, in nanoseconds
     489      * @since 1.5
     490      */
     491     @IntrinsicCandidate
     492     public static native long nanoTime();
     493
     494     /**
     495      * Copies an array from the specified source array, beginning at the
     496      * specified position, to the specified position of the destination array.
     497      * A subsequence of array components are copied from the source
     498      * array referenced by {@code src} to the destination array
     499      * referenced by {@code dest}. The number of components copied is
     500      * equal to the {@code length} argument. The components at
     501      * positions {@code srcPos} through
     502      * {@code srcPos+length-1} in the source array are copied into
     503      * positions {@code destPos} through
     504      * {@code destPos+length-1}, respectively, of the destination
     505      * array.
     506      * <p>
     507      * If the {@code src} and {@code dest} arguments refer to the
     508      * same array object, then the copying is performed as if the
     509      * components at positions {@code srcPos} through
     510      * {@code srcPos+length-1} were first copied to a temporary
     511      * array with {@code length} components and then the contents of
     512      * the temporary array were copied into positions
     513      * {@code destPos} through {@code destPos+length-1} of the
     514      * destination array.
     515      * <p>
     516      * If {@code dest} is {@code null}, then a
     517      * {@code NullPointerException} is thrown.
     518      * <p>
     519      * If {@code src} is {@code null}, then a
     520      * {@code NullPointerException} is thrown and the destination
     521      * array is not modified.
     522      * <p>
     523      * Otherwise, if any of the following is true, an
     524      * {@code ArrayStoreException} is thrown and the destination is
     525      * not modified:
     526      * <ul>
     527      * <li>The {@code src} argument refers to an object that is not an
     528      *     array.
     529      * <li>The {@code dest} argument refers to an object that is not an
     530      *     array.
     531      * <li>The {@code src} argument and {@code dest} argument refer
     532      *     to arrays whose component types are different primitive types.
     533      * <li>The {@code src} argument refers to an array with a primitive
     534      *    component type and the {@code dest} argument refers to an array
     535      *     with a reference component type.
     536      * <li>The {@code src} argument refers to an array with a reference
     537      *    component type and the {@code dest} argument refers to an array
     538      *     with a primitive component type.
     539      * </ul>
     540      * <p>
     541      * Otherwise, if any of the following is true, an
     542      * {@code IndexOutOfBoundsException} is
     543      * thrown and the destination is not modified:
     544      * <ul>
     545      * <li>The {@code srcPos} argument is negative.
     546      * <li>The {@code destPos} argument is negative.
     547      * <li>The {@code length} argument is negative.
     548      * <li>{@code srcPos+length} is greater than
     549      *     {@code src.length}, the length of the source array.
     550      * <li>{@code destPos+length} is greater than
     551      *     {@code dest.length}, the length of the destination array.
     552      * </ul>
     553      * <p>
     554      * Otherwise, if any actual component of the source array from
     555      * position {@code srcPos} through
     556      * {@code srcPos+length-1} cannot be converted to the component
     557      * type of the destination array by assignment conversion, an
     558      * {@code ArrayStoreException} is thrown. In this case, let
     559      * <b><i>k</i></b> be the smallest nonnegative integer less than
     560      * length such that {@code src[srcPos+}<i>k</i>{@code ]}
     561      * cannot be converted to the component type of the destination
     562      * array; when the exception is thrown, source array components from
     563      * positions {@code srcPos} through
     564      * {@code srcPos+}<i>k</i>{@code -1}
     565      * will already have been copied to destination array positions
     566      * {@code destPos} through
     567      * {@code destPos+}<i>k</I>{@code -1} and no other
     568      * positions of the destination array will have been modified.
     569      * (Because of the restrictions already itemized, this
     570      * paragraph effectively applies only to the situation where both
     571      * arrays have component types that are reference types.)
     572      *
     573      * @param      src      the source array.
     574      * @param      srcPos   starting position in the source array.
     575      * @param      dest     the destination array.
     576      * @param      destPos  starting position in the destination data.
     577      * @param      length   the number of array elements to be copied.
     578      * @throws     IndexOutOfBoundsException  if copying would cause
     579      *             access of data outside array bounds.
     580      * @throws     ArrayStoreException  if an element in the {@code src}
     581      *             array could not be stored into the {@code dest} array
     582      *             because of a type mismatch.
     583      * @throws     NullPointerException if either {@code src} or
     584      *             {@code dest} is {@code null}.
     585      */
     586     @IntrinsicCandidate
     587     public static native void arraycopy(Object src,  int  srcPos,
     588                                         Object dest, int destPos,
     589                                         int length);
     590
     591     /**
     592      * Returns the same hash code for the given object as
     593      * would be returned by the default method hashCode(),
     594      * whether or not the given object's class overrides
     595      * hashCode().
     596      * The hash code for the null reference is zero.
     597      *
     598      * @param x object for which the hashCode is to be calculated
     599      * @return  the hashCode
     600      * @since   1.1
     601      * @see Object#hashCode
     602      * @see java.util.Objects#hashCode(Object)
     603      */
     604     @IntrinsicCandidate
     605     public static native int identityHashCode(Object x);
     606
     607     /**
     608      * System properties.
     609      *
     610      * See {@linkplain #getProperties getProperties} for details.
     611      */
     612     private static Properties props;
     613
     614     /**
     615      * Determines the current system properties.
     616      *
     617      * First, if there is a security manager, its
     618      * {@code checkPropertiesAccess} method is called with no
     619      * arguments. This may result in a security exception.
     620      * <p>
     621      * The current set of system properties for use by the
     622      * {@link #getProperty(String)} method is returned as a
     623      * {@code Properties} object. If there is no current set of
     624      * system properties, a set of system properties is first created and
     625      * initialized. This set of system properties includes a value
     626      * for each of the following keys unless the description of the associated
     627      * value indicates that the value is optional.
     628      * <table class="striped" style="text-align:left">
     629      * <caption style="display:none">Shows property keys and associated values</caption>
     630      * <thead>
     631      * <tr><th scope="col">Key</th>
     632      *     <th scope="col">Description of Associated Value</th></tr>
     633      * </thead>
     634      * <tbody>
     635      * <tr><th scope="row">{@systemProperty java.version}</th>
     636      *     <td>Java Runtime Environment version, which may be interpreted
     637      *     as a {@link Runtime.Version}</td></tr>
     638      * <tr><th scope="row">{@systemProperty java.version.date}</th>
     639      *     <td>Java Runtime Environment version date, in ISO-8601 YYYY-MM-DD
     640      *     format, which may be interpreted as a {@link
     641      *     java.time.LocalDate}</td></tr>
     642      * <tr><th scope="row">{@systemProperty java.vendor}</th>
     643      *     <td>Java Runtime Environment vendor</td></tr>
     644      * <tr><th scope="row">{@systemProperty java.vendor.url}</th>
     645      *     <td>Java vendor URL</td></tr>
     646      * <tr><th scope="row">{@systemProperty java.vendor.version}</th>
     647      *     <td>Java vendor version <em>(optional)</em> </td></tr>
     648      * <tr><th scope="row">{@systemProperty java.home}</th>
     649      *     <td>Java installation directory</td></tr>
     650      * <tr><th scope="row">{@systemProperty java.vm.specification.version}</th>
     651      *     <td>Java Virtual Machine specification version, whose value is the
     652      *     {@linkplain Runtime.Version#feature feature} element of the
     653      *     {@linkplain Runtime#version() runtime version}</td></tr>
     654      * <tr><th scope="row">{@systemProperty java.vm.specification.vendor}</th>
     655      *     <td>Java Virtual Machine specification vendor</td></tr>
     656      * <tr><th scope="row">{@systemProperty java.vm.specification.name}</th>
     657      *     <td>Java Virtual Machine specification name</td></tr>
     658      * <tr><th scope="row">{@systemProperty java.vm.version}</th>
     659      *     <td>Java Virtual Machine implementation version which may be
     660      *     interpreted as a {@link Runtime.Version}</td></tr>
     661      * <tr><th scope="row">{@systemProperty java.vm.vendor}</th>
     662      *     <td>Java Virtual Machine implementation vendor</td></tr>
     663      * <tr><th scope="row">{@systemProperty java.vm.name}</th>
     664      *     <td>Java Virtual Machine implementation name</td></tr>
     665      * <tr><th scope="row">{@systemProperty java.specification.version}</th>
     666      *     <td>Java Runtime Environment specification version, whose value is
     667      *     the {@linkplain Runtime.Version#feature feature} element of the
     668      *     {@linkplain Runtime#version() runtime version}</td></tr>
     669      * <tr><th scope="row">{@systemProperty java.specification.vendor}</th>
     670      *     <td>Java Runtime Environment specification  vendor</td></tr>
     671      * <tr><th scope="row">{@systemProperty java.specification.name}</th>
     672      *     <td>Java Runtime Environment specification  name</td></tr>
     673      * <tr><th scope="row">{@systemProperty java.class.version}</th>
     674      *     <td>Java class format version number</td></tr>
     675      * <tr><th scope="row">{@systemProperty java.class.path}</th>
     676      *     <td>Java class path  (refer to
     677      *        {@link ClassLoader#getSystemClassLoader()} for details)</td></tr>
     678      * <tr><th scope="row">{@systemProperty java.library.path}</th>
     679      *     <td>List of paths to search when loading libraries</td></tr>
     680      * <tr><th scope="row">{@systemProperty java.io.tmpdir}</th>
     681      *     <td>Default temp file path</td></tr>
     682      * <tr><th scope="row">{@systemProperty java.compiler}</th>
     683      *     <td>Name of JIT compiler to use</td></tr>
     684      * <tr><th scope="row">{@systemProperty os.name}</th>
     685      *     <td>Operating system name</td></tr>
     686      * <tr><th scope="row">{@systemProperty os.arch}</th>
     687      *     <td>Operating system architecture</td></tr>
     688      * <tr><th scope="row">{@systemProperty os.version}</th>
     689      *     <td>Operating system version</td></tr>
     690      * <tr><th scope="row">{@systemProperty file.separator}</th>
     691      *     <td>File separator ("/" on UNIX)</td></tr>
     692      * <tr><th scope="row">{@systemProperty path.separator}</th>
     693      *     <td>Path separator (":" on UNIX)</td></tr>
     694      * <tr><th scope="row">{@systemProperty line.separator}</th>
     695      *     <td>Line separator ("\n" on UNIX)</td></tr>
     696      * <tr><th scope="row">{@systemProperty user.name}</th>
     697      *     <td>User's account name</td></tr>
     698      * <tr><th scope="row">{@systemProperty user.home}</th>
     699      *     <td>User's home directory</td></tr>
     700      * <tr><th scope="row">{@systemProperty user.dir}</th>
     701      *     <td>User's current working directory</td></tr>
     702      * <tr><th scope="row">{@systemProperty native.encoding}</th>
     703      *     <td>Character encoding name derived from the host environment and/or
     704      *     the user's settings. Setting this system property has no effect.</td></tr>
     705      * </tbody>
     706      * </table>
     707      * <p>
     708      * Multiple paths in a system property value are separated by the path
     709      * separator character of the platform.
     710      * <p>
     711      * Note that even if the security manager does not permit the
     712      * {@code getProperties} operation, it may choose to permit the
     713      * {@link #getProperty(String)} operation.
     714      *
     715      * @apiNote
     716      * <strong>Changing a standard system property may have unpredictable results
     717      * unless otherwise specified.</strong>
     718      * Property values may be cached during initialization or on first use.
     719      * Setting a standard property after initialization using {@link #getProperties()},
     720      * {@link #setProperties(Properties)}, {@link #setProperty(String, String)}, or
     721      * {@link #clearProperty(String)} may not have the desired effect.
     722      *
     723      * @implNote
     724      * In addition to the standard system properties, the system
     725      * properties may include the following keys:
     726      * <table class="striped">
     727      * <caption style="display:none">Shows property keys and associated values</caption>
     728      * <thead>
     729      * <tr><th scope="col">Key</th>
     730      *     <th scope="col">Description of Associated Value</th></tr>
     731      * </thead>
     732      * <tbody>
     733      * <tr><th scope="row">{@systemProperty jdk.module.path}</th>
     734      *     <td>The application module path</td></tr>
     735      * <tr><th scope="row">{@systemProperty jdk.module.upgrade.path}</th>
     736      *     <td>The upgrade module path</td></tr>
     737      * <tr><th scope="row">{@systemProperty jdk.module.main}</th>
     738      *     <td>The module name of the initial/main module</td></tr>
     739      * <tr><th scope="row">{@systemProperty jdk.module.main.class}</th>
     740      *     <td>The main class name of the initial module</td></tr>
     741      * </tbody>
     742      * </table>
     743      *
     744      * @return     the system properties
     745      * @throws     SecurityException  if a security manager exists and its
     746      *             {@code checkPropertiesAccess} method doesn't allow access
     747      *             to the system properties.
     748      * @see        #setProperties
     749      * @see        java.lang.SecurityException
     750      * @see        java.lang.SecurityManager#checkPropertiesAccess()
     751      * @see        java.util.Properties
     752      */
     753     public static Properties getProperties() {
     754         SecurityManager sm = getSecurityManager();
     755         if (sm != null) {
     756             sm.checkPropertiesAccess();
     757         }
     758
     759         return props;
     760     }
     761
     762     /**
     763      * Returns the system-dependent line separator string.  It always
     764      * returns the same value - the initial value of the {@linkplain
     765      * #getProperty(String) system property} {@code line.separator}.
     766      *
     767      * <p>On UNIX systems, it returns {@code "\n"}; on Microsoft
     768      * Windows systems it returns {@code "\r\n"}.
     769      *
     770      * @return the system-dependent line separator string
     771      * @since 1.7
     772      */
     773     public static String lineSeparator() {
     774         return lineSeparator;
     775     }
     776
     777     private static String lineSeparator;
     778
     779     /**
     780      * Sets the system properties to the {@code Properties} argument.
     781      *
     782      * First, if there is a security manager, its
     783      * {@code checkPropertiesAccess} method is called with no
     784      * arguments. This may result in a security exception.
     785      * <p>
     786      * The argument becomes the current set of system properties for use
     787      * by the {@link #getProperty(String)} method. If the argument is
     788      * {@code null}, then the current set of system properties is
     789      * forgotten.
     790      *
     791      * @apiNote
     792      * <strong>Changing a standard system property may have unpredictable results
     793      * unless otherwise specified</strong>.
     794      * See {@linkplain #getProperties getProperties} for details.
     795      *
     796      * @param      props   the new system properties.
     797      * @throws     SecurityException  if a security manager exists and its
     798      *             {@code checkPropertiesAccess} method doesn't allow access
     799      *             to the system properties.
     800      * @see        #getProperties
     801      * @see        java.util.Properties
     802      * @see        java.lang.SecurityException
     803      * @see        java.lang.SecurityManager#checkPropertiesAccess()
     804      */
     805     public static void setProperties(Properties props) {
     806         SecurityManager sm = getSecurityManager();
     807         if (sm != null) {
     808             sm.checkPropertiesAccess();
     809         }
     810
     811         if (props == null) {
     812             Map<String, String> tempProps = SystemProps.initProperties();
     813             VersionProps.init(tempProps);
     814             props = createProperties(tempProps);
     815         }
     816         System.props = props;
     817     }
     818
     819     /**
     820      * Gets the system property indicated by the specified key.
     821      *
     822      * First, if there is a security manager, its
     823      * {@code checkPropertyAccess} method is called with the key as
     824      * its argument. This may result in a SecurityException.
     825      * <p>
     826      * If there is no current set of system properties, a set of system
     827      * properties is first created and initialized in the same manner as
     828      * for the {@code getProperties} method.
     829      *
     830      * @apiNote
     831      * <strong>Changing a standard system property may have unpredictable results
     832      * unless otherwise specified</strong>.
     833      * See {@linkplain #getProperties getProperties} for details.
     834      *
     835      * @param      key   the name of the system property.
     836      * @return     the string value of the system property,
     837      *             or {@code null} if there is no property with that key.
     838      *
     839      * @throws     SecurityException  if a security manager exists and its
     840      *             {@code checkPropertyAccess} method doesn't allow
     841      *             access to the specified system property.
     842      * @throws     NullPointerException if {@code key} is {@code null}.
     843      * @throws     IllegalArgumentException if {@code key} is empty.
     844      * @see        #setProperty
     845      * @see        java.lang.SecurityException
     846      * @see        java.lang.SecurityManager#checkPropertyAccess(java.lang.String)
     847      * @see        java.lang.System#getProperties()
     848      */
     849     public static String getProperty(String key) {
     850         checkKey(key);
     851         SecurityManager sm = getSecurityManager();
     852         if (sm != null) {
     853             sm.checkPropertyAccess(key);
     854         }
     855
     856         return props.getProperty(key);
     857     }
     858
     859     /**
     860      * Gets the system property indicated by the specified key.
     861      *
     862      * First, if there is a security manager, its
     863      * {@code checkPropertyAccess} method is called with the
     864      * {@code key} as its argument.
     865      * <p>
     866      * If there is no current set of system properties, a set of system
     867      * properties is first created and initialized in the same manner as
     868      * for the {@code getProperties} method.
     869      *
     870      * @param      key   the name of the system property.
     871      * @param      def   a default value.
     872      * @return     the string value of the system property,
     873      *             or the default value if there is no property with that key.
     874      *
     875      * @throws     SecurityException  if a security manager exists and its
     876      *             {@code checkPropertyAccess} method doesn't allow
     877      *             access to the specified system property.
     878      * @throws     NullPointerException if {@code key} is {@code null}.
     879      * @throws     IllegalArgumentException if {@code key} is empty.
     880      * @see        #setProperty
     881      * @see        java.lang.SecurityManager#checkPropertyAccess(java.lang.String)
     882      * @see        java.lang.System#getProperties()
     883      */
     884     public static String getProperty(String key, String def) {
     885         checkKey(key);
     886         SecurityManager sm = getSecurityManager();
     887         if (sm != null) {
     888             sm.checkPropertyAccess(key);
     889         }
     890
     891         return props.getProperty(key, def);
     892     }
     893
     894     /**
     895      * Sets the system property indicated by the specified key.
     896      *
     897      * First, if a security manager exists, its
     898      * {@code SecurityManager.checkPermission} method
     899      * is called with a {@code PropertyPermission(key, "write")}
     900      * permission. This may result in a SecurityException being thrown.
     901      * If no exception is thrown, the specified property is set to the given
     902      * value.
     903      *
     904      * @apiNote
     905      * <strong>Changing a standard system property may have unpredictable results
     906      * unless otherwise specified</strong>.
     907      * See {@linkplain #getProperties getProperties} for details.
     908      *
     909      * @param      key   the name of the system property.
     910      * @param      value the value of the system property.
     911      * @return     the previous value of the system property,
     912      *             or {@code null} if it did not have one.
     913      *
     914      * @throws     SecurityException  if a security manager exists and its
     915      *             {@code checkPermission} method doesn't allow
     916      *             setting of the specified property.
     917      * @throws     NullPointerException if {@code key} or
     918      *             {@code value} is {@code null}.
     919      * @throws     IllegalArgumentException if {@code key} is empty.
     920      * @see        #getProperty
     921      * @see        java.lang.System#getProperty(java.lang.String)
     922      * @see        java.lang.System#getProperty(java.lang.String, java.lang.String)
     923      * @see        java.util.PropertyPermission
     924      * @see        SecurityManager#checkPermission
     925      * @since      1.2
     926      */
     927     public static String setProperty(String key, String value) {
     928         checkKey(key);
     929         SecurityManager sm = getSecurityManager();
     930         if (sm != null) {
     931             sm.checkPermission(new PropertyPermission(key,
     932                 SecurityConstants.PROPERTY_WRITE_ACTION));
     933         }
     934
     935         return (String) props.setProperty(key, value);
     936     }
     937
     938     /**
     939      * Removes the system property indicated by the specified key.
     940      *
     941      * First, if a security manager exists, its
     942      * {@code SecurityManager.checkPermission} method
     943      * is called with a {@code PropertyPermission(key, "write")}
     944      * permission. This may result in a SecurityException being thrown.
     945      * If no exception is thrown, the specified property is removed.
     946      *
     947      * @apiNote
     948      * <strong>Changing a standard system property may have unpredictable results
     949      * unless otherwise specified</strong>.
     950      * See {@linkplain #getProperties getProperties} method for details.
     951      *
     952      * @param      key   the name of the system property to be removed.
     953      * @return     the previous string value of the system property,
     954      *             or {@code null} if there was no property with that key.
     955      *
     956      * @throws     SecurityException  if a security manager exists and its
     957      *             {@code checkPropertyAccess} method doesn't allow
     958      *              access to the specified system property.
     959      * @throws     NullPointerException if {@code key} is {@code null}.
     960      * @throws     IllegalArgumentException if {@code key} is empty.
     961      * @see        #getProperty
     962      * @see        #setProperty
     963      * @see        java.util.Properties
     964      * @see        java.lang.SecurityException
     965      * @see        java.lang.SecurityManager#checkPropertiesAccess()
     966      * @since 1.5
     967      */
     968     public static String clearProperty(String key) {
     969         checkKey(key);
     970         SecurityManager sm = getSecurityManager();
     971         if (sm != null) {
     972             sm.checkPermission(new PropertyPermission(key, "write"));
     973         }
     974
     975         return (String) props.remove(key);
     976     }
     977
     978     private static void checkKey(String key) {
     979         if (key == null) {
     980             throw new NullPointerException("key can't be null");
     981         }
     982         if (key.isEmpty()) {
     983             throw new IllegalArgumentException("key can't be empty");
     984         }
     985     }
     986
     987     /**
     988      * Gets the value of the specified environment variable. An
     989      * environment variable is a system-dependent external named
     990      * value.
     991      *
     992      * <p>If a security manager exists, its
     993      * {@link SecurityManager#checkPermission checkPermission}
     994      * method is called with a
     995      * {@link RuntimePermission RuntimePermission("getenv."+name)}
     996      * permission.  This may result in a {@link SecurityException}
     997      * being thrown.  If no exception is thrown the value of the
     998      * variable {@code name} is returned.
     999      *
    1000      * <p><a id="EnvironmentVSSystemProperties"><i>System
    1001      * properties</i> and <i>environment variables</i></a> are both
    1002      * conceptually mappings between names and values.  Both
    1003      * mechanisms can be used to pass user-defined information to a
    1004      * Java process.  Environment variables have a more global effect,
    1005      * because they are visible to all descendants of the process
    1006      * which defines them, not just the immediate Java subprocess.
    1007      * They can have subtly different semantics, such as case
    1008      * insensitivity, on different operating systems.  For these
    1009      * reasons, environment variables are more likely to have
    1010      * unintended side effects.  It is best to use system properties
    1011      * where possible.  Environment variables should be used when a
    1012      * global effect is desired, or when an external system interface
    1013      * requires an environment variable (such as {@code PATH}).
    1014      *
    1015      * <p>On UNIX systems the alphabetic case of {@code name} is
    1016      * typically significant, while on Microsoft Windows systems it is
    1017      * typically not.  For example, the expression
    1018      * {@code System.getenv("FOO").equals(System.getenv("foo"))}
    1019      * is likely to be true on Microsoft Windows.
    1020      *
    1021      * @param  name the name of the environment variable
    1022      * @return the string value of the variable, or {@code null}
    1023      *         if the variable is not defined in the system environment
    1024      * @throws NullPointerException if {@code name} is {@code null}
    1025      * @throws SecurityException
    1026      *         if a security manager exists and its
    1027      *         {@link SecurityManager#checkPermission checkPermission}
    1028      *         method doesn't allow access to the environment variable
    1029      *         {@code name}
    1030      * @see    #getenv()
    1031      * @see    ProcessBuilder#environment()
    1032      */
    1033     public static String getenv(String name) {
    1034         SecurityManager sm = getSecurityManager();
    1035         if (sm != null) {
    1036             sm.checkPermission(new RuntimePermission("getenv."+name));
    1037         }
    1038
    1039         return ProcessEnvironment.getenv(name);
    1040     }
    1041
    1042
    1043     /**
    1044      * Returns an unmodifiable string map view of the current system environment.
    1045      * The environment is a system-dependent mapping from names to
    1046      * values which is passed from parent to child processes.
    1047      *
    1048      * <p>If the system does not support environment variables, an
    1049      * empty map is returned.
    1050      *
    1051      * <p>The returned map will never contain null keys or values.
    1052      * Attempting to query the presence of a null key or value will
    1053      * throw a {@link NullPointerException}.  Attempting to query
    1054      * the presence of a key or value which is not of type
    1055      * {@link String} will throw a {@link ClassCastException}.
    1056      *
    1057      * <p>The returned map and its collection views may not obey the
    1058      * general contract of the {@link Object#equals} and
    1059      * {@link Object#hashCode} methods.
    1060      *
    1061      * <p>The returned map is typically case-sensitive on all platforms.
    1062      *
    1063      * <p>If a security manager exists, its
    1064      * {@link SecurityManager#checkPermission checkPermission}
    1065      * method is called with a
    1066      * {@link RuntimePermission RuntimePermission("getenv.*")} permission.
    1067      * This may result in a {@link SecurityException} being thrown.
    1068      *
    1069      * <p>When passing information to a Java subprocess,
    1070      * <a href=#EnvironmentVSSystemProperties>system properties</a>
    1071      * are generally preferred over environment variables.
    1072      *
    1073      * @return the environment as a map of variable names to values
    1074      * @throws SecurityException
    1075      *         if a security manager exists and its
    1076      *         {@link SecurityManager#checkPermission checkPermission}
    1077      *         method doesn't allow access to the process environment
    1078      * @see    #getenv(String)
    1079      * @see    ProcessBuilder#environment()
    1080      * @since  1.5
    1081      */
    1082     public static java.util.Map<String,String> getenv() {
    1083         SecurityManager sm = getSecurityManager();
    1084         if (sm != null) {
    1085             sm.checkPermission(new RuntimePermission("getenv.*"));
    1086         }
    1087
    1088         return ProcessEnvironment.getenv();
    1089     }
    1090
    1091     /**
    1092      * {@code System.Logger} instances log messages that will be
    1093      * routed to the underlying logging framework the {@link System.LoggerFinder
    1094      * LoggerFinder} uses.
    1095      *
    1096      * {@code System.Logger} instances are typically obtained from
    1097      * the {@link java.lang.System System} class, by calling
    1098      * {@link java.lang.System#getLogger(java.lang.String) System.getLogger(loggerName)}
    1099      * or {@link java.lang.System#getLogger(java.lang.String, java.util.ResourceBundle)
    1100      * System.getLogger(loggerName, bundle)}.
    1101      *
    1102      * @see java.lang.System#getLogger(java.lang.String)
    1103      * @see java.lang.System#getLogger(java.lang.String, java.util.ResourceBundle)
    1104      * @see java.lang.System.LoggerFinder
    1105      *
    1106      * @since 9
    1107      */
    1108     public interface Logger {
    1109
    1110         /**
    1111          * System {@linkplain Logger loggers} levels.
    1112          *
    1113          * A level has a {@linkplain #getName() name} and {@linkplain
    1114          * #getSeverity() severity}.
    1115          * Level values are {@link #ALL}, {@link #TRACE}, {@link #DEBUG},
    1116          * {@link #INFO}, {@link #WARNING}, {@link #ERROR}, {@link #OFF},
    1117          * by order of increasing severity.
    1118          * <br>
    1119          * {@link #ALL} and {@link #OFF}
    1120          * are simple markers with severities mapped respectively to
    1121          * {@link java.lang.Integer#MIN_VALUE Integer.MIN_VALUE} and
    1122          * {@link java.lang.Integer#MAX_VALUE Integer.MAX_VALUE}.
    1123          * <p>
    1124          * <b>Severity values and Mapping to {@code java.util.logging.Level}.</b>
    1125          * <p>
    1126          * {@linkplain System.Logger.Level System logger levels} are mapped to
    1127          * {@linkplain java.util.logging.Level  java.util.logging levels}
    1128          * of corresponding severity.
    1129          * <br>The mapping is as follows:
    1130          * <br><br>
    1131          * <table class="striped">
    1132          * <caption>System.Logger Severity Level Mapping</caption>
    1133          * <thead>
    1134          * <tr><th scope="col">System.Logger Levels</th>
    1135          *     <th scope="col">java.util.logging Levels</th>
    1136          * </thead>
    1137          * <tbody>
    1138          * <tr><th scope="row">{@link Logger.Level#ALL ALL}</th>
    1139          *     <td>{@link java.util.logging.Level#ALL ALL}</td>
    1140          * <tr><th scope="row">{@link Logger.Level#TRACE TRACE}</th>
    1141          *     <td>{@link java.util.logging.Level#FINER FINER}</td>
    1142          * <tr><th scope="row">{@link Logger.Level#DEBUG DEBUG}</th>
    1143          *     <td>{@link java.util.logging.Level#FINE FINE}</td>
    1144          * <tr><th scope="row">{@link Logger.Level#INFO INFO}</th>
    1145          *     <td>{@link java.util.logging.Level#INFO INFO}</td>
    1146          * <tr><th scope="row">{@link Logger.Level#WARNING WARNING}</th>
    1147          *     <td>{@link java.util.logging.Level#WARNING WARNING}</td>
    1148          * <tr><th scope="row">{@link Logger.Level#ERROR ERROR}</th>
    1149          *     <td>{@link java.util.logging.Level#SEVERE SEVERE}</td>
    1150          * <tr><th scope="row">{@link Logger.Level#OFF OFF}</th>
    1151          *     <td>{@link java.util.logging.Level#OFF OFF}</td>
    1152          * </tbody>
    1153          * </table>
    1154          *
    1155          * @since 9
    1156          *
    1157          * @see java.lang.System.LoggerFinder
    1158          * @see java.lang.System.Logger
    1159          */
    1160         public enum Level {
    1161
    1162             // for convenience, we're reusing java.util.logging.Level int values
    1163             // the mapping logic in sun.util.logging.PlatformLogger depends
    1164             // on this.
    1165             /**
    1166              * A marker to indicate that all levels are enabled.
    1167              * This level {@linkplain #getSeverity() severity} is
    1168              * {@link Integer#MIN_VALUE}.
    1169              */
    1170             ALL(Integer.MIN_VALUE),  // typically mapped to/from j.u.l.Level.ALL
    1171             /**
    1172              * {@code TRACE} level: usually used to log diagnostic information.
    1173              * This level {@linkplain #getSeverity() severity} is
    1174              * {@code 400}.
    1175              */
    1176             TRACE(400),   // typically mapped to/from j.u.l.Level.FINER
    1177             /**
    1178              * {@code DEBUG} level: usually used to log debug information traces.
    1179              * This level {@linkplain #getSeverity() severity} is
    1180              * {@code 500}.
    1181              */
    1182             DEBUG(500),   // typically mapped to/from j.u.l.Level.FINEST/FINE/CONFIG
    1183             /**
    1184              * {@code INFO} level: usually used to log information messages.
    1185              * This level {@linkplain #getSeverity() severity} is
    1186              * {@code 800}.
    1187              */
    1188             INFO(800),    // typically mapped to/from j.u.l.Level.INFO
    1189             /**
    1190              * {@code WARNING} level: usually used to log warning messages.
    1191              * This level {@linkplain #getSeverity() severity} is
    1192              * {@code 900}.
    1193              */
    1194             WARNING(900), // typically mapped to/from j.u.l.Level.WARNING
    1195             /**
    1196              * {@code ERROR} level: usually used to log error messages.
    1197              * This level {@linkplain #getSeverity() severity} is
    1198              * {@code 1000}.
    1199              */
    1200             ERROR(1000),  // typically mapped to/from j.u.l.Level.SEVERE
    1201             /**
    1202              * A marker to indicate that all levels are disabled.
    1203              * This level {@linkplain #getSeverity() severity} is
    1204              * {@link Integer#MAX_VALUE}.
    1205              */
    1206             OFF(Integer.MAX_VALUE);  // typically mapped to/from j.u.l.Level.OFF
    1207
    1208             private final int severity;
    1209
    1210             private Level(int severity) {
    1211                 this.severity = severity;
    1212             }
    1213
    1214             /**
    1215              * Returns the name of this level.
    1216              * @return this level {@linkplain #name()}.
    1217              */
    1218             public final String getName() {
    1219                 return name();
    1220             }
    1221
    1222             /**
    1223              * Returns the severity of this level.
    1224              * A higher severity means a more severe condition.
    1225              * @return this level severity.
    1226              */
    1227             public final int getSeverity() {
    1228                 return severity;
    1229             }
    1230         }
    1231
    1232         /**
    1233          * Returns the name of this logger.
    1234          *
    1235          * @return the logger name.
    1236          */
    1237         public String getName();
    1238
    1239         /**
    1240          * Checks if a message of the given level would be logged by
    1241          * this logger.
    1242          *
    1243          * @param level the log message level.
    1244          * @return {@code true} if the given log message level is currently
    1245          *         being logged.
    1246          *
    1247          * @throws NullPointerException if {@code level} is {@code null}.
    1248          */
    1249         public boolean isLoggable(Level level);
    1250
    1251         /**
    1252          * Logs a message.
    1253          *
    1254          * @implSpec The default implementation for this method calls
    1255          * {@code this.log(level, (ResourceBundle)null, msg, (Object[])null);}
    1256          *
    1257          * @param level the log message level.
    1258          * @param msg the string message (or a key in the message catalog, if
    1259          * this logger is a {@link
    1260          * LoggerFinder#getLocalizedLogger(java.lang.String,
    1261          * java.util.ResourceBundle, java.lang.Module) localized logger});
    1262          * can be {@code null}.
    1263          *
    1264          * @throws NullPointerException if {@code level} is {@code null}.
    1265          */
    1266         public default void log(Level level, String msg) {
    1267             log(level, (ResourceBundle) null, msg, (Object[]) null);
    1268         }
    1269
    1270         /**
    1271          * Logs a lazily supplied message.
    1272          *
    1273          * If the logger is currently enabled for the given log message level
    1274          * then a message is logged that is the result produced by the
    1275          * given supplier function.  Otherwise, the supplier is not operated on.
    1276          *
    1277          * @implSpec When logging is enabled for the given level, the default
    1278          * implementation for this method calls
    1279          * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), (Object[])null);}
    1280          *
    1281          * @param level the log message level.
    1282          * @param msgSupplier a supplier function that produces a message.
    1283          *
    1284          * @throws NullPointerException if {@code level} is {@code null},
    1285          *         or {@code msgSupplier} is {@code null}.
    1286          */
    1287         public default void log(Level level, Supplier<String> msgSupplier) {
    1288             Objects.requireNonNull(msgSupplier);
    1289             if (isLoggable(Objects.requireNonNull(level))) {
    1290                 log(level, (ResourceBundle) null, msgSupplier.get(), (Object[]) null);
    1291             }
    1292         }
    1293
    1294         /**
    1295          * Logs a message produced from the given object.
    1296          *
    1297          * If the logger is currently enabled for the given log message level then
    1298          * a message is logged that, by default, is the result produced from
    1299          * calling  toString on the given object.
    1300          * Otherwise, the object is not operated on.
    1301          *
    1302          * @implSpec When logging is enabled for the given level, the default
    1303          * implementation for this method calls
    1304          * {@code this.log(level, (ResourceBundle)null, obj.toString(), (Object[])null);}
    1305          *
    1306          * @param level the log message level.
    1307          * @param obj the object to log.
    1308          *
    1309          * @throws NullPointerException if {@code level} is {@code null}, or
    1310          *         {@code obj} is {@code null}.
    1311          */
    1312         public default void log(Level level, Object obj) {
    1313             Objects.requireNonNull(obj);
    1314             if (isLoggable(Objects.requireNonNull(level))) {
    1315                 this.log(level, (ResourceBundle) null, obj.toString(), (Object[]) null);
    1316             }
    1317         }
    1318
    1319         /**
    1320          * Logs a message associated with a given throwable.
    1321          *
    1322          * @implSpec The default implementation for this method calls
    1323          * {@code this.log(level, (ResourceBundle)null, msg, thrown);}
    1324          *
    1325          * @param level the log message level.
    1326          * @param msg the string message (or a key in the message catalog, if
    1327          * this logger is a {@link
    1328          * LoggerFinder#getLocalizedLogger(java.lang.String,
    1329          * java.util.ResourceBundle, java.lang.Module) localized logger});
    1330          * can be {@code null}.
    1331          * @param thrown a {@code Throwable} associated with the log message;
    1332          *        can be {@code null}.
    1333          *
    1334          * @throws NullPointerException if {@code level} is {@code null}.
    1335          */
    1336         public default void log(Level level, String msg, Throwable thrown) {
    1337             this.log(level, null, msg, thrown);
    1338         }
    1339
    1340         /**
    1341          * Logs a lazily supplied message associated with a given throwable.
    1342          *
    1343          * If the logger is currently enabled for the given log message level
    1344          * then a message is logged that is the result produced by the
    1345          * given supplier function.  Otherwise, the supplier is not operated on.
    1346          *
    1347          * @implSpec When logging is enabled for the given level, the default
    1348          * implementation for this method calls
    1349          * {@code this.log(level, (ResourceBundle)null, msgSupplier.get(), thrown);}
    1350          *
    1351          * @param level one of the log message level identifiers.
    1352          * @param msgSupplier a supplier function that produces a message.
    1353          * @param thrown a {@code Throwable} associated with log message;
    1354          *               can be {@code null}.
    1355          *
    1356          * @throws NullPointerException if {@code level} is {@code null}, or
    1357          *                               {@code msgSupplier} is {@code null}.
    1358          */
    1359         public default void log(Level level, Supplier<String> msgSupplier,
    1360                 Throwable thrown) {
    1361             Objects.requireNonNull(msgSupplier);
    1362             if (isLoggable(Objects.requireNonNull(level))) {
    1363                 this.log(level, null, msgSupplier.get(), thrown);
    1364             }
    1365         }
    1366
    1367         /**
    1368          * Logs a message with an optional list of parameters.
    1369          *
    1370          * @implSpec The default implementation for this method calls
    1371          * {@code this.log(level, (ResourceBundle)null, format, params);}
    1372          *
    1373          * @param level one of the log message level identifiers.
    1374          * @param format the string message format in {@link
    1375          * java.text.MessageFormat} format, (or a key in the message
    1376          * catalog, if this logger is a {@link
    1377          * LoggerFinder#getLocalizedLogger(java.lang.String,
    1378          * java.util.ResourceBundle, java.lang.Module) localized logger});
    1379          * can be {@code null}.
    1380          * @param params an optional list of parameters to the message (may be
    1381          * none).
    1382          *
    1383          * @throws NullPointerException if {@code level} is {@code null}.
    1384          */
    1385         public default void log(Level level, String format, Object... params) {
    1386             this.log(level, null, format, params);
    1387         }
    1388
    1389         /**
    1390          * Logs a localized message associated with a given throwable.
    1391          *
    1392          * If the given resource bundle is non-{@code null},  the {@code msg}
    1393          * string is localized using the given resource bundle.
    1394          * Otherwise the {@code msg} string is not localized.
    1395          *
    1396          * @param level the log message level.
    1397          * @param bundle a resource bundle to localize {@code msg}; can be
    1398          * {@code null}.
    1399          * @param msg the string message (or a key in the message catalog,
    1400          *            if {@code bundle} is not {@code null}); can be {@code null}.
    1401          * @param thrown a {@code Throwable} associated with the log message;
    1402          *        can be {@code null}.
    1403          *
    1404          * @throws NullPointerException if {@code level} is {@code null}.
    1405          */
    1406         public void log(Level level, ResourceBundle bundle, String msg,
    1407                 Throwable thrown);
    1408
    1409         /**
    1410          * Logs a message with resource bundle and an optional list of
    1411          * parameters.
    1412          *
    1413          * If the given resource bundle is non-{@code null},  the {@code format}
    1414          * string is localized using the given resource bundle.
    1415          * Otherwise the {@code format} string is not localized.
    1416          *
    1417          * @param level the log message level.
    1418          * @param bundle a resource bundle to localize {@code format}; can be
    1419          * {@code null}.
    1420          * @param format the string message format in {@link
    1421          * java.text.MessageFormat} format, (or a key in the message
    1422          * catalog if {@code bundle} is not {@code null}); can be {@code null}.
    1423          * @param params an optional list of parameters to the message (may be
    1424          * none).
    1425          *
    1426          * @throws NullPointerException if {@code level} is {@code null}.
    1427          */
    1428         public void log(Level level, ResourceBundle bundle, String format,
    1429                 Object... params);
    1430     }
    1431
    1432     /**
    1433      * The {@code LoggerFinder} service is responsible for creating, managing,
    1434      * and configuring loggers to the underlying framework it uses.
    1435      *
    1436      * A logger finder is a concrete implementation of this class that has a
    1437      * zero-argument constructor and implements the abstract methods defined
    1438      * by this class.
    1439      * The loggers returned from a logger finder are capable of routing log
    1440      * messages to the logging backend this provider supports.
    1441      * A given invocation of the Java Runtime maintains a single
    1442      * system-wide LoggerFinder instance that is loaded as follows:
    1443      * <ul>
    1444      *    <li>First it finds any custom {@code LoggerFinder} provider
    1445      *        using the {@link java.util.ServiceLoader} facility with the
    1446      *        {@linkplain ClassLoader#getSystemClassLoader() system class
    1447      *        loader}.</li>
    1448      *    <li>If no {@code LoggerFinder} provider is found, the system default
    1449      *        {@code LoggerFinder} implementation will be used.</li>
    1450      * </ul>
    1451      * <p>
    1452      * An application can replace the logging backend
    1453      * <i>even when the java.logging module is present</i>, by simply providing
    1454      * and declaring an implementation of the {@link LoggerFinder} service.
    1455      * <p>
    1456      * <b>Default Implementation</b>
    1457      * <p>
    1458      * The system default {@code LoggerFinder} implementation uses
    1459      * {@code java.util.logging} as the backend framework when the
    1460      * {@code java.logging} module is present.
    1461      * It returns a {@linkplain System.Logger logger} instance
    1462      * that will route log messages to a {@link java.util.logging.Logger
    1463      * java.util.logging.Logger}. Otherwise, if {@code java.logging} is not
    1464      * present, the default implementation will return a simple logger
    1465      * instance that will route log messages of {@code INFO} level and above to
    1466      * the console ({@code System.err}).
    1467      * <p>
    1468      * <b>Logging Configuration</b>
    1469      * <p>
    1470      * {@linkplain Logger Logger} instances obtained from the
    1471      * {@code LoggerFinder} factory methods are not directly configurable by
    1472      * the application. Configuration is the responsibility of the underlying
    1473      * logging backend, and usually requires using APIs specific to that backend.
    1474      * <p>For the default {@code LoggerFinder} implementation
    1475      * using {@code java.util.logging} as its backend, refer to
    1476      * {@link java.util.logging java.util.logging} for logging configuration.
    1477      * For the default {@code LoggerFinder} implementation returning simple loggers
    1478      * when the {@code java.logging} module is absent, the configuration
    1479      * is implementation dependent.
    1480      * <p>
    1481      * Usually an application that uses a logging framework will log messages
    1482      * through a logger facade defined (or supported) by that framework.
    1483      * Applications that wish to use an external framework should log
    1484      * through the facade associated with that framework.
    1485      * <p>
    1486      * A system class that needs to log messages will typically obtain
    1487      * a {@link System.Logger} instance to route messages to the logging
    1488      * framework selected by the application.
    1489      * <p>
    1490      * Libraries and classes that only need loggers to produce log messages
    1491      * should not attempt to configure loggers by themselves, as that
    1492      * would make them dependent from a specific implementation of the
    1493      * {@code LoggerFinder} service.
    1494      * <p>
    1495      * In addition, when a security manager is present, loggers provided to
    1496      * system classes should not be directly configurable through the logging
    1497      * backend without requiring permissions.
    1498      * <br>
    1499      * It is the responsibility of the provider of
    1500      * the concrete {@code LoggerFinder} implementation to ensure that
    1501      * these loggers are not configured by untrusted code without proper
    1502      * permission checks, as configuration performed on such loggers usually
    1503      * affects all applications in the same Java Runtime.
    1504      * <p>
    1505      * <b>Message Levels and Mapping to backend levels</b>
    1506      * <p>
    1507      * A logger finder is responsible for mapping from a {@code
    1508      * System.Logger.Level} to a level supported by the logging backend it uses.
    1509      * <br>The default LoggerFinder using {@code java.util.logging} as the backend
    1510      * maps {@code System.Logger} levels to
    1511      * {@linkplain java.util.logging.Level java.util.logging} levels
    1512      * of corresponding severity - as described in {@link Logger.Level
    1513      * Logger.Level}.
    1514      *
    1515      * @see java.lang.System
    1516      * @see java.lang.System.Logger
    1517      *
    1518      * @since 9
    1519      */
    1520     public static abstract class LoggerFinder {
    1521         /**
    1522          * The {@code RuntimePermission("loggerFinder")} is
    1523          * necessary to subclass and instantiate the {@code LoggerFinder} class,
    1524          * as well as to obtain loggers from an instance of that class.
    1525          */
    1526         static final RuntimePermission LOGGERFINDER_PERMISSION =
    1527                 new RuntimePermission("loggerFinder");
    1528
    1529         /**
    1530          * Creates a new instance of {@code LoggerFinder}.
    1531          *
    1532          * @implNote It is recommended that a {@code LoggerFinder} service
    1533          *   implementation does not perform any heavy initialization in its
    1534          *   constructor, in order to avoid possible risks of deadlock or class
    1535          *   loading cycles during the instantiation of the service provider.
    1536          *
    1537          * @throws SecurityException if a security manager is present and its
    1538          *         {@code checkPermission} method doesn't allow the
    1539          *         {@code RuntimePermission("loggerFinder")}.
    1540          */
    1541         protected LoggerFinder() {
    1542             this(checkPermission());
    1543         }
    1544
    1545         private LoggerFinder(Void unused) {
    1546             // nothing to do.
    1547         }
    1548
    1549         private static Void checkPermission() {
    1550             final SecurityManager sm = System.getSecurityManager();
    1551             if (sm != null) {
    1552                 sm.checkPermission(LOGGERFINDER_PERMISSION);
    1553             }
    1554             return null;
    1555         }
    1556
    1557         /**
    1558          * Returns an instance of {@link Logger Logger}
    1559          * for the given {@code module}.
    1560          *
    1561          * @param name the name of the logger.
    1562          * @param module the module for which the logger is being requested.
    1563          *
    1564          * @return a {@link Logger logger} suitable for use within the given
    1565          *         module.
    1566          * @throws NullPointerException if {@code name} is {@code null} or
    1567          *        {@code module} is {@code null}.
    1568          * @throws SecurityException if a security manager is present and its
    1569          *         {@code checkPermission} method doesn't allow the
    1570          *         {@code RuntimePermission("loggerFinder")}.
    1571          */
    1572         public abstract Logger getLogger(String name, Module module);
    1573
    1574         /**
    1575          * Returns a localizable instance of {@link Logger Logger}
    1576          * for the given {@code module}.
    1577          * The returned logger will use the provided resource bundle for
    1578          * message localization.
    1579          *
    1580          * @implSpec By default, this method calls {@link
    1581          * #getLogger(java.lang.String, java.lang.Module)
    1582          * this.getLogger(name, module)} to obtain a logger, then wraps that
    1583          * logger in a {@link Logger} instance where all methods that do not
    1584          * take a {@link ResourceBundle} as parameter are redirected to one
    1585          * which does - passing the given {@code bundle} for
    1586          * localization. So for instance, a call to {@link
    1587          * Logger#log(Logger.Level, String) Logger.log(Level.INFO, msg)}
    1588          * will end up as a call to {@link
    1589          * Logger#log(Logger.Level, ResourceBundle, String, Object...)
    1590          * Logger.log(Level.INFO, bundle, msg, (Object[])null)} on the wrapped
    1591          * logger instance.
    1592          * Note however that by default, string messages returned by {@link
    1593          * java.util.function.Supplier Supplier&lt;String&gt;} will not be
    1594          * localized, as it is assumed that such strings are messages which are
    1595          * already constructed, rather than keys in a resource bundle.
    1596          * <p>
    1597          * An implementation of {@code LoggerFinder} may override this method,
    1598          * for example, when the underlying logging backend provides its own
    1599          * mechanism for localizing log messages, then such a
    1600          * {@code LoggerFinder} would be free to return a logger
    1601          * that makes direct use of the mechanism provided by the backend.
    1602          *
    1603          * @param name    the name of the logger.
    1604          * @param bundle  a resource bundle; can be {@code null}.
    1605          * @param module  the module for which the logger is being requested.
    1606          * @return an instance of {@link Logger Logger}  which will use the
    1607          * provided resource bundle for message localization.
    1608          *
    1609          * @throws NullPointerException if {@code name} is {@code null} or
    1610          *         {@code module} is {@code null}.
    1611          * @throws SecurityException if a security manager is present and its
    1612          *         {@code checkPermission} method doesn't allow the
    1613          *         {@code RuntimePermission("loggerFinder")}.
    1614          */
    1615         public Logger getLocalizedLogger(String name, ResourceBundle bundle,
    1616                                          Module module) {
    1617             return new LocalizedLoggerWrapper<>(getLogger(name, module), bundle);
    1618         }
    1619
    1620         /**
    1621          * Returns the {@code LoggerFinder} instance. There is one
    1622          * single system-wide {@code LoggerFinder} instance in
    1623          * the Java Runtime.  See the class specification of how the
    1624          * {@link LoggerFinder LoggerFinder} implementation is located and
    1625          * loaded.
    1626          *
    1627          * @return the {@link LoggerFinder LoggerFinder} instance.
    1628          * @throws SecurityException if a security manager is present and its
    1629          *         {@code checkPermission} method doesn't allow the
    1630          *         {@code RuntimePermission("loggerFinder")}.
    1631          */
    1632         public static LoggerFinder getLoggerFinder() {
    1633             final SecurityManager sm = System.getSecurityManager();
    1634             if (sm != null) {
    1635                 sm.checkPermission(LOGGERFINDER_PERMISSION);
    1636             }
    1637             return accessProvider();
    1638         }
    1639
    1640
    1641         private static volatile LoggerFinder service;
    1642         static LoggerFinder accessProvider() {
    1643             // We do not need to synchronize: LoggerFinderLoader will
    1644             // always return the same instance, so if we don't have it,
    1645             // just fetch it again.
    1646             if (service == null) {
    1647                 PrivilegedAction<LoggerFinder> pa =
    1648                         () -> LoggerFinderLoader.getLoggerFinder();
    1649                 service = AccessController.doPrivileged(pa, null,
    1650                         LOGGERFINDER_PERMISSION);
    1651             }
    1652             return service;
    1653         }
    1654
    1655     }
    1656
    1657
    1658     /**
    1659      * Returns an instance of {@link Logger Logger} for the caller's
    1660      * use.
    1661      *
    1662      * @implSpec
    1663      * Instances returned by this method route messages to loggers
    1664      * obtained by calling {@link LoggerFinder#getLogger(java.lang.String,
    1665      * java.lang.Module) LoggerFinder.getLogger(name, module)}, where
    1666      * {@code module} is the caller's module.
    1667      * In cases where {@code System.getLogger} is called from a context where
    1668      * there is no caller frame on the stack (e.g when called directly
    1669      * from a JNI attached thread), {@code IllegalCallerException} is thrown.
    1670      * To obtain a logger in such a context, use an auxiliary class that will
    1671      * implicitly be identified as the caller, or use the system {@link
    1672      * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead.
    1673      * Note that doing the latter may eagerly initialize the underlying
    1674      * logging system.
    1675      *
    1676      * @apiNote
    1677      * This method may defer calling the {@link
    1678      * LoggerFinder#getLogger(java.lang.String, java.lang.Module)
    1679      * LoggerFinder.getLogger} method to create an actual logger supplied by
    1680      * the logging backend, for instance, to allow loggers to be obtained during
    1681      * the system initialization time.
    1682      *
    1683      * @param name the name of the logger.
    1684      * @return an instance of {@link Logger} that can be used by the calling
    1685      *         class.
    1686      * @throws NullPointerException if {@code name} is {@code null}.
    1687      * @throws IllegalCallerException if there is no Java caller frame on the
    1688      *         stack.
    1689      *
    1690      * @since 9
    1691      */
    1692     @CallerSensitive
    1693     public static Logger getLogger(String name) {
    1694         Objects.requireNonNull(name);
    1695         final Class<?> caller = Reflection.getCallerClass();
    1696         if (caller == null) {
    1697             throw new IllegalCallerException("no caller frame");
    1698         }
    1699         return LazyLoggers.getLogger(name, caller.getModule());
    1700     }
    1701
    1702     /**
    1703      * Returns a localizable instance of {@link Logger
    1704      * Logger} for the caller's use.
    1705      * The returned logger will use the provided resource bundle for message
    1706      * localization.
    1707      *
    1708      * @implSpec
    1709      * The returned logger will perform message localization as specified
    1710      * by {@link LoggerFinder#getLocalizedLogger(java.lang.String,
    1711      * java.util.ResourceBundle, java.lang.Module)
    1712      * LoggerFinder.getLocalizedLogger(name, bundle, module)}, where
    1713      * {@code module} is the caller's module.
    1714      * In cases where {@code System.getLogger} is called from a context where
    1715      * there is no caller frame on the stack (e.g when called directly
    1716      * from a JNI attached thread), {@code IllegalCallerException} is thrown.
    1717      * To obtain a logger in such a context, use an auxiliary class that
    1718      * will implicitly be identified as the caller, or use the system {@link
    1719      * LoggerFinder#getLoggerFinder() LoggerFinder} to obtain a logger instead.
    1720      * Note that doing the latter may eagerly initialize the underlying
    1721      * logging system.
    1722      *
    1723      * @apiNote
    1724      * This method is intended to be used after the system is fully initialized.
    1725      * This method may trigger the immediate loading and initialization
    1726      * of the {@link LoggerFinder} service, which may cause issues if the
    1727      * Java Runtime is not ready to initialize the concrete service
    1728      * implementation yet.
    1729      * System classes which may be loaded early in the boot sequence and
    1730      * need to log localized messages should create a logger using
    1731      * {@link #getLogger(java.lang.String)} and then use the log methods that
    1732      * take a resource bundle as parameter.
    1733      *
    1734      * @param name    the name of the logger.
    1735      * @param bundle  a resource bundle.
    1736      * @return an instance of {@link Logger} which will use the provided
    1737      * resource bundle for message localization.
    1738      * @throws NullPointerException if {@code name} is {@code null} or
    1739      *         {@code bundle} is {@code null}.
    1740      * @throws IllegalCallerException if there is no Java caller frame on the
    1741      *         stack.
    1742      *
    1743      * @since 9
    1744      */
    1745     @CallerSensitive
    1746     public static Logger getLogger(String name, ResourceBundle bundle) {
    1747         final ResourceBundle rb = Objects.requireNonNull(bundle);
    1748         Objects.requireNonNull(name);
    1749         final Class<?> caller = Reflection.getCallerClass();
    1750         if (caller == null) {
    1751             throw new IllegalCallerException("no caller frame");
    1752         }
    1753         final SecurityManager sm = System.getSecurityManager();
    1754         // We don't use LazyLoggers if a resource bundle is specified.
    1755         // Bootstrap sensitive classes in the JDK do not use resource bundles
    1756         // when logging. This could be revisited later, if it needs to.
    1757         if (sm != null) {
    1758             final PrivilegedAction<Logger> pa =
    1759                     () -> LoggerFinder.accessProvider()
    1760                             .getLocalizedLogger(name, rb, caller.getModule());
    1761             return AccessController.doPrivileged(pa, null,
    1762                                          LoggerFinder.LOGGERFINDER_PERMISSION);
    1763         }
    1764         return LoggerFinder.accessProvider()
    1765                 .getLocalizedLogger(name, rb, caller.getModule());
    1766     }
    1767
    1768     /**
    1769      * Terminates the currently running Java Virtual Machine. The
    1770      * argument serves as a status code; by convention, a nonzero status
    1771      * code indicates abnormal termination.
    1772      * <p>
    1773      * This method calls the {@code exit} method in class
    1774      * {@code Runtime}. This method never returns normally.
    1775      * <p>
    1776      * The call {@code System.exit(n)} is effectively equivalent to
    1777      * the call:
    1778      * <blockquote><pre>
    1779      * Runtime.getRuntime().exit(n)
    1780      * </pre></blockquote>
    1781      *
    1782      * @param      status   exit status.
    1783      * @throws  SecurityException
    1784      *        if a security manager exists and its {@code checkExit}
    1785      *        method doesn't allow exit with the specified status.
    1786      * @see        java.lang.Runtime#exit(int)
    1787      */
    1788     public static void exit(int status) {
    1789         Runtime.getRuntime().exit(status);
    1790     }
    1791
    1792     /**
    1793      * Runs the garbage collector in the Java Virtual Machine.
    1794      * <p>
    1795      * Calling the {@code gc} method suggests that the Java Virtual Machine
    1796      * expend effort toward recycling unused objects in order to
    1797      * make the memory they currently occupy available for reuse
    1798      * by the Java Virtual Machine.
    1799      * When control returns from the method call, the Java Virtual Machine
    1800      * has made a best effort to reclaim space from all unused objects.
    1801      * There is no guarantee that this effort will recycle any particular
    1802      * number of unused objects, reclaim any particular amount of space, or
    1803      * complete at any particular time, if at all, before the method returns or ever.
    1804      * <p>
    1805      * The call {@code System.gc()} is effectively equivalent to the
    1806      * call:
    1807      * <blockquote><pre>
    1808      * Runtime.getRuntime().gc()
    1809      * </pre></blockquote>
    1810      *
    1811      * @see     java.lang.Runtime#gc()
    1812      */
    1813     public static void gc() {
    1814         Runtime.getRuntime().gc();
    1815     }
    1816
    1817     /**
    1818      * Runs the finalization methods of any objects pending finalization.
    1819      *
    1820      * Calling this method suggests that the Java Virtual Machine expend
    1821      * effort toward running the {@code finalize} methods of objects
    1822      * that have been found to be discarded but whose {@code finalize}
    1823      * methods have not yet been run. When control returns from the
    1824      * method call, the Java Virtual Machine has made a best effort to
    1825      * complete all outstanding finalizations.
    1826      * <p>
    1827      * The call {@code System.runFinalization()} is effectively
    1828      * equivalent to the call:
    1829      * <blockquote><pre>
    1830      * Runtime.getRuntime().runFinalization()
    1831      * </pre></blockquote>
    1832      *
    1833      * @see     java.lang.Runtime#runFinalization()
    1834      */
    1835     public static void runFinalization() {
    1836         Runtime.getRuntime().runFinalization();
    1837     }
    1838
    1839     /**
    1840      * Loads the native library specified by the filename argument.  The filename
    1841      * argument must be an absolute path name.
    1842      *
    1843      * If the filename argument, when stripped of any platform-specific library
    1844      * prefix, path, and file extension, indicates a library whose name is,
    1845      * for example, L, and a native library called L is statically linked
    1846      * with the VM, then the JNI_OnLoad_L function exported by the library
    1847      * is invoked rather than attempting to load a dynamic library.
    1848      * A filename matching the argument does not have to exist in the
    1849      * file system.
    1850      * See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
    1851      * for more details.
    1852      *
    1853      * Otherwise, the filename argument is mapped to a native library image in
    1854      * an implementation-dependent manner.
    1855      *
    1856      * <p>
    1857      * The call {@code System.load(name)} is effectively equivalent
    1858      * to the call:
    1859      * <blockquote><pre>
    1860      * Runtime.getRuntime().load(name)
    1861      * </pre></blockquote>
    1862      *
    1863      * @param      filename   the file to load.
    1864      * @throws     SecurityException  if a security manager exists and its
    1865      *             {@code checkLink} method doesn't allow
    1866      *             loading of the specified dynamic library
    1867      * @throws     UnsatisfiedLinkError  if either the filename is not an
    1868      *             absolute path name, the native library is not statically
    1869      *             linked with the VM, or the library cannot be mapped to
    1870      *             a native library image by the host system.
    1871      * @throws     NullPointerException if {@code filename} is {@code null}
    1872      * @see        java.lang.Runtime#load(java.lang.String)
    1873      * @see        java.lang.SecurityManager#checkLink(java.lang.String)
    1874      */
    1875     @CallerSensitive
    1876     public static void load(String filename) {
    1877         Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
    1878     }
    1879
    1880     /**
    1881      * Loads the native library specified by the {@code libname}
    1882      * argument.  The {@code libname} argument must not contain any platform
    1883      * specific prefix, file extension or path. If a native library
    1884      * called {@code libname} is statically linked with the VM, then the
    1885      * JNI_OnLoad_{@code libname} function exported by the library is invoked.
    1886      * See the <a href="{@docRoot}/../specs/jni/index.html"> JNI Specification</a>
    1887      * for more details.
    1888      *
    1889      * Otherwise, the libname argument is loaded from a system library
    1890      * location and mapped to a native library image in an
    1891      * implementation-dependent manner.
    1892      * <p>
    1893      * The call {@code System.loadLibrary(name)} is effectively
    1894      * equivalent to the call
    1895      * <blockquote><pre>
    1896      * Runtime.getRuntime().loadLibrary(name)
    1897      * </pre></blockquote>
    1898      *
    1899      * @param      libname   the name of the library.
    1900      * @throws     SecurityException  if a security manager exists and its
    1901      *             {@code checkLink} method doesn't allow
    1902      *             loading of the specified dynamic library
    1903      * @throws     UnsatisfiedLinkError if either the libname argument
    1904      *             contains a file path, the native library is not statically
    1905      *             linked with the VM,  or the library cannot be mapped to a
    1906      *             native library image by the host system.
    1907      * @throws     NullPointerException if {@code libname} is {@code null}
    1908      * @see        java.lang.Runtime#loadLibrary(java.lang.String)
    1909      * @see        java.lang.SecurityManager#checkLink(java.lang.String)
    1910      */
    1911     @CallerSensitive
    1912     public static void loadLibrary(String libname) {
    1913         Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
    1914     }
    1915
    1916     /**
    1917      * Maps a library name into a platform-specific string representing
    1918      * a native library.
    1919      *
    1920      * @param      libname the name of the library.
    1921      * @return     a platform-dependent native library name.
    1922      * @throws     NullPointerException if {@code libname} is {@code null}
    1923      * @see        java.lang.System#loadLibrary(java.lang.String)
    1924      * @see        java.lang.ClassLoader#findLibrary(java.lang.String)
    1925      * @since      1.2
    1926      */
    1927     public static native String mapLibraryName(String libname);
    1928
    1929     /**
    1930      * Create PrintStream for stdout/err based on encoding.
    1931      */
    1932     private static PrintStream newPrintStream(FileOutputStream fos, String enc) {
    1933        if (enc != null) {
    1934             try {
    1935                 return new PrintStream(new BufferedOutputStream(fos, 128), true, enc);
    1936             } catch (UnsupportedEncodingException uee) {}
    1937         }
    1938         return new PrintStream(new BufferedOutputStream(fos, 128), true);
    1939     }
    1940
    1941     /**
    1942      * Logs an exception/error at initialization time to stdout or stderr.
    1943      *
    1944      * @param printToStderr to print to stderr rather than stdout
    1945      * @param printStackTrace to print the stack trace
    1946      * @param msg the message to print before the exception, can be {@code null}
    1947      * @param e the exception or error
    1948      */
    1949     private static void logInitException(boolean printToStderr,
    1950                                          boolean printStackTrace,
    1951                                          String msg,
    1952                                          Throwable e) {
    1953         if (VM.initLevel() < 1) {
    1954             throw new InternalError("system classes not initialized");
    1955         }
    1956         PrintStream log = (printToStderr) ? err : out;
    1957         if (msg != null) {
    1958             log.println(msg);
    1959         }
    1960         if (printStackTrace) {
    1961             e.printStackTrace(log);
    1962         } else {
    1963             log.println(e);
    1964             for (Throwable suppressed : e.getSuppressed()) {
    1965                 log.println("Suppressed: " + suppressed);
    1966             }
    1967             Throwable cause = e.getCause();
    1968             if (cause != null) {
    1969                 log.println("Caused by: " + cause);
    1970             }
    1971         }
    1972     }
    1973
    1974     /**
    1975      * Create the Properties object from a map - masking out system properties
    1976      * that are not intended for public access.
    1977      */
    1978     private static Properties createProperties(Map<String, String> initialProps) {
    1979         Properties properties = new Properties(initialProps.size());
    1980         for (var entry : initialProps.entrySet()) {
    1981             String prop = entry.getKey();
    1982             switch (prop) {
    1983                 // Do not add private system properties to the Properties
    1984                 case "sun.nio.MaxDirectMemorySize":
    1985                 case "sun.nio.PageAlignDirectMemory":
    1986                     // used by java.lang.Integer.IntegerCache
    1987                 case "java.lang.Integer.IntegerCache.high":
    1988                     // used by sun.launcher.LauncherHelper
    1989                 case "sun.java.launcher.diag":
    1990                     // used by jdk.internal.loader.ClassLoaders
    1991                 case "jdk.boot.class.path.append":
    1992                     break;
    1993                 default:
    1994                     properties.put(prop, entry.getValue());
    1995             }
    1996         }
    1997         return properties;
    1998     }
    1999
    2000     /**
    2001      * Initialize the system class.  Called after thread initialization.
    2002      */
    2003     private static void initPhase1() {
    2004
    2005         // register the shared secrets - do this first, since SystemProps.initProperties
    2006         // might initialize CharsetDecoders that rely on it
    2007         setJavaLangAccess();
    2008
    2009         // VM might invoke JNU_NewStringPlatform() to set those encoding
    2010         // sensitive properties (user.home, user.name, boot.class.path, etc.)
    2011         // during "props" initialization.
    2012         // The charset is initialized in System.c and does not depend on the Properties.
    2013         Map<String, String> tempProps = SystemProps.initProperties();
    2014         VersionProps.init(tempProps);
    2015
    2016         // There are certain system configurations that may be controlled by
    2017         // VM options such as the maximum amount of direct memory and
    2018         // Integer cache size used to support the object identity semantics
    2019         // of autoboxing.  Typically, the library will obtain these values
    2020         // from the properties set by the VM.  If the properties are for
    2021         // internal implementation use only, these properties should be
    2022         // masked from the system properties.
    2023         //
    2024         // Save a private copy of the system properties object that
    2025         // can only be accessed by the internal implementation.
    2026         VM.saveProperties(tempProps);
    2027         props = createProperties(tempProps);
    2028
    2029         StaticProperty.javaHome();          // Load StaticProperty to cache the property values
    2030
    2031         lineSeparator = props.getProperty("line.separator");
    2032
    2033         FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
    2034         FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
    2035         FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
    2036         setIn0(new BufferedInputStream(fdIn));
    2037         // sun.stdout/err.encoding are set when the VM is associated with the terminal,
    2038         // thus they are equivalent to Console.charset(), otherwise the encoding
    2039         // defaults to Charset.defaultCharset()
    2040         setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
    2041         setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
    2042
    2043         // Setup Java signal handlers for HUP, TERM, and INT (where available).
    2044         Terminator.setup();
    2045
    2046         // Initialize any miscellaneous operating system settings that need to be
    2047         // set for the class libraries. Currently this is no-op everywhere except
    2048         // for Windows where the process-wide error mode is set before the java.io
    2049         // classes are used.
    2050         VM.initializeOSEnvironment();
    2051
    2052         // The main thread is not added to its thread group in the same
    2053         // way as other threads; we must do it ourselves here.
    2054         Thread current = Thread.currentThread();
    2055         current.getThreadGroup().add(current);
    2056
    2057
    2058         // Subsystems that are invoked during initialization can invoke
    2059         // VM.isBooted() in order to avoid doing things that should
    2060         // wait until the VM is fully initialized. The initialization level
    2061         // is incremented from 0 to 1 here to indicate the first phase of
    2062         // initialization has completed.
    2063         // IMPORTANT: Ensure that this remains the last initialization action!
    2064         VM.initLevel(1);
    2065     }
    2066
    2067     // @see #initPhase2()
    2068     static ModuleLayer bootLayer;
    2069
    2070     /*
    2071      * Invoked by VM.  Phase 2 module system initialization.
    2072      * Only classes in java.base can be loaded in this phase.
    2073      *
    2074      * @param printToStderr print exceptions to stderr rather than stdout
    2075      * @param printStackTrace print stack trace when exception occurs
    2076      *
    2077      * @return JNI_OK for success, JNI_ERR for failure
    2078      */
    2079     private static int initPhase2(boolean printToStderr, boolean printStackTrace) {
    2080
    2081         try {
    2082             bootLayer = ModuleBootstrap.boot();
    2083         } catch (Exception | Error e) {
    2084             logInitException(printToStderr, printStackTrace,
    2085                              "Error occurred during initialization of boot layer", e);
    2086             return -1; // JNI_ERR
    2087         }
    2088
    2089         // module system initialized
    2090         VM.initLevel(2);
    2091
    2092         return 0; // JNI_OK
    2093     }
    2094
    2095     /*
    2096      * Invoked by VM.  Phase 3 is the final system initialization:
    2097      * 1. eagerly initialize bootstrap method factories that might interact
    2098      *    negatively with custom security managers and custom class loaders
    2099      * 2. set security manager
    2100      * 3. set system class loader
    2101      * 4. set TCCL
    2102      *
    2103      * This method must be called after the module system initialization.
    2104      * The security manager and system class loader may be a custom class from
    2105      * the application classpath or modulepath.
    2106      */
    2107     private static void initPhase3() {
    2108
    2109         // Initialize the StringConcatFactory eagerly to avoid potential
    2110         // bootstrap circularity issues that could be caused by a custom
    2111         // SecurityManager
    2112         Unsafe.getUnsafe().ensureClassInitialized(StringConcatFactory.class);
    2113
    2114         String smProp = System.getProperty("java.security.manager");
    2115         if (smProp != null) {
    2116             switch (smProp) {
    2117                 case "disallow":
    2118                     allowSecurityManager = NEVER;
    2119                     break;
    2120                 case "allow":
    2121                     allowSecurityManager = MAYBE;
    2122                     break;
    2123                 case "":
    2124                 case "default":
    2125                     setSecurityManager(new SecurityManager());
    2126                     allowSecurityManager = MAYBE;
    2127                     break;
    2128                 default:
    2129                     try {
    2130                         ClassLoader cl = ClassLoader.getBuiltinAppClassLoader();
    2131                         Class<?> c = Class.forName(smProp, false, cl);
    2132                         Constructor<?> ctor = c.getConstructor();
    2133                         // Must be a public subclass of SecurityManager with
    2134                         // a public no-arg constructor
    2135                         if (!SecurityManager.class.isAssignableFrom(c) ||
    2136                             !Modifier.isPublic(c.getModifiers()) ||
    2137                             !Modifier.isPublic(ctor.getModifiers())) {
    2138                             throw new Error("Could not create SecurityManager: "
    2139                                              + ctor.toString());
    2140                         }
    2141                         // custom security manager may be in non-exported package
    2142                         ctor.setAccessible(true);
    2143                         SecurityManager sm = (SecurityManager) ctor.newInstance();
    2144                         setSecurityManager(sm);
    2145                     } catch (Exception e) {
    2146                         throw new InternalError("Could not create SecurityManager", e);
    2147                     }
    2148                     allowSecurityManager = MAYBE;
    2149             }
    2150         } else {
    2151             allowSecurityManager = MAYBE;

    2152         }
    2153
    2154         // initializing the system class loader
    2155         VM.initLevel(3);
    2156
    2157         // system class loader initialized
    2158         ClassLoader scl = ClassLoader.initSystemClassLoader();
    2159
    2160         // set TCCL
    2161         Thread.currentThread().setContextClassLoader(scl);
    2162
    2163         // system is fully initialized
    2164         VM.initLevel(4);
    2165     }
    2166
    2167     private static void setJavaLangAccess() {
    2168         // Allow privileged classes outside of java.lang
    2169         SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
    2170             public List<Method> getDeclaredPublicMethods(Class<?> klass, String name, Class<?>... parameterTypes) {
    2171                 return klass.getDeclaredPublicMethods(name, parameterTypes);
    2172             }
    2173             public jdk.internal.reflect.ConstantPool getConstantPool(Class<?> klass) {
    2174                 return klass.getConstantPool();
    2175             }
    2176             public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
    2177                 return klass.casAnnotationType(oldType, newType);
    2178             }
    2179             public AnnotationType getAnnotationType(Class<?> klass) {
    2180                 return klass.getAnnotationType();
    2181             }
    2182             public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) {
    2183                 return klass.getDeclaredAnnotationMap();
    2184             }
    2185             public byte[] getRawClassAnnotations(Class<?> klass) {
    2186                 return klass.getRawAnnotations();
    2187             }
    2188             public byte[] getRawClassTypeAnnotations(Class<?> klass) {
    2189                 return klass.getRawTypeAnnotations();
    2190             }
    2191             public byte[] getRawExecutableTypeAnnotations(Executable executable) {
    2192                 return Class.getExecutableTypeAnnotationBytes(executable);
    2193             }
    2194             public <E extends Enum<E>>
    2195             E[] getEnumConstantsShared(Class<E> klass) {
    2196                 return klass.getEnumConstantsShared();
    2197             }
    2198             public void blockedOn(Interruptible b) {
    2199                 Thread.blockedOn(b);
    2200             }
    2201             public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
    2202                 Shutdown.add(slot, registerShutdownInProgress, hook);
    2203             }
    2204             public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) {
    2205                 return new Thread(target, acc);
    2206             }
    2207             @SuppressWarnings("deprecation")
    2208             public void invokeFinalize(Object o) throws Throwable {
    2209                 o.finalize();
    2210             }
    2211             public ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl) {
    2212                 return cl.createOrGetClassLoaderValueMap();
    2213             }
    2214             public Class<?> defineClass(ClassLoader loader, String name, byte[] b, ProtectionDomain pd, String source) {
    2215                 return ClassLoader.defineClass1(loader, name, b, 0, b.length, pd, source);
    2216             }
    2217             public Class<?> defineClass(ClassLoader loader, Class<?> lookup, String name, byte[] b, ProtectionDomain pd,
    2218                                         boolean initialize, int flags, Object classData) {
    2219                 return ClassLoader.defineClass0(loader, lookup, name, b, 0, b.length, pd, initialize, flags, classData);
    2220             }
    2221             public Class<?> findBootstrapClassOrNull(String name) {
    2222                 return ClassLoader.findBootstrapClassOrNull(name);
    2223             }
    2224             public Package definePackage(ClassLoader cl, String name, Module module) {
    2225                 return cl.definePackage(name, module);
    2226             }
    2227             public String fastUUID(long lsb, long msb) {
    2228                 return Long.fastUUID(lsb, msb);
    2229             }
    2230             public void addNonExportedPackages(ModuleLayer layer) {
    2231                 SecurityManager.addNonExportedPackages(layer);
    2232             }
    2233             public void invalidatePackageAccessCache() {
    2234                 SecurityManager.invalidatePackageAccessCache();
    2235             }
    2236             public Module defineModule(ClassLoader loader,
    2237                                        ModuleDescriptor descriptor,
    2238                                        URI uri) {
    2239                 return new Module(null, loader, descriptor, uri);
    2240             }
    2241             public Module defineUnnamedModule(ClassLoader loader) {
    2242                 return new Module(loader);
    2243             }
    2244             public void addReads(Module m1, Module m2) {
    2245                 m1.implAddReads(m2);
    2246             }
    2247             public void addReadsAllUnnamed(Module m) {
    2248                 m.implAddReadsAllUnnamed();
    2249             }
    2250             public void addExports(Module m, String pn) {
    2251                 m.implAddExports(pn);
    2252             }
    2253             public void addExports(Module m, String pn, Module other) {
    2254                 m.implAddExports(pn, other);
    2255             }
    2256             public void addExportsToAllUnnamed(Module m, String pn) {
    2257                 m.implAddExportsToAllUnnamed(pn);
    2258             }
    2259             public void addOpens(Module m, String pn, Module other) {
    2260                 m.implAddOpens(pn, other);
    2261             }
    2262             public void addOpensToAllUnnamed(Module m, String pn) {
    2263                 m.implAddOpensToAllUnnamed(pn);
    2264             }
    2265             public void addOpensToAllUnnamed(Module m, Set<String> concealedPackages, Set<String> exportedPackages) {
    2266                 m.implAddOpensToAllUnnamed(concealedPackages, exportedPackages);
    2267             }
    2268             public void addUses(Module m, Class<?> service) {
    2269                 m.implAddUses(service);
    2270             }
    2271             public boolean isReflectivelyExported(Module m, String pn, Module other) {
    2272                 return m.isReflectivelyExported(pn, other);
    2273             }
    2274             public boolean isReflectivelyOpened(Module m, String pn, Module other) {
    2275                 return m.isReflectivelyOpened(pn, other);
    2276             }
    2277             public ServicesCatalog getServicesCatalog(ModuleLayer layer) {
    2278                 return layer.getServicesCatalog();
    2279             }
    2280             public void bindToLoader(ModuleLayer layer, ClassLoader loader) {
    2281                 layer.bindToLoader(loader);
    2282             }
    2283             public Stream<ModuleLayer> layers(ModuleLayer layer) {
    2284                 return layer.layers();
    2285             }
    2286             public Stream<ModuleLayer> layers(ClassLoader loader) {
    2287                 return ModuleLayer.layers(loader);
    2288             }
    2289
    2290             public String newStringNoRepl(byte[] bytes, Charset cs) throws CharacterCodingException  {
    2291                 return String.newStringNoRepl(bytes, cs);
    2292             }
    2293
    2294             public byte[] getBytesNoRepl(String s, Charset cs) throws CharacterCodingException {
    2295                 return String.getBytesNoRepl(s, cs);
    2296             }
    2297
    2298             public String newStringUTF8NoRepl(byte[] bytes, int off, int len) {
    2299                 return String.newStringUTF8NoRepl(bytes, off, len);
    2300             }
    2301
    2302             public byte[] getBytesUTF8NoRepl(String s) {
    2303                 return String.getBytesUTF8NoRepl(s);
    2304             }
    2305
    2306             public void inflateBytesToChars(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
    2307                 StringLatin1.inflate(src, srcOff, dst, dstOff, len);
    2308             }
    2309
    2310             public int decodeASCII(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
    2311                 return String.decodeASCII(src, srcOff, dst, dstOff, len);
    2312             }
    2313
    2314             public void setCause(Throwable t, Throwable cause) {
    2315                 t.setCause(cause);
    2316             }
    2317
    2318             public ProtectionDomain protectionDomain(Class<?> c) {
    2319                 return c.protectionDomain();
    2320             }
    2321
    2322             public MethodHandle stringConcatHelper(String name, MethodType methodType) {
    2323                 return StringConcatHelper.lookupStatic(name, methodType);
    2324             }
    2325
    2326             public long stringConcatInitialCoder() {
    2327                 return StringConcatHelper.initialCoder();
    2328             }
    2329
    2330             public long stringConcatMix(long lengthCoder, String constant) {
    2331                 return StringConcatHelper.mix(lengthCoder, constant);
    2332             }
    2333
    2334             public String join(String prefix, String suffix, String delimiter, String[] elements, int size) {
    2335                 return String.join(prefix, suffix, delimiter, elements, size);
    2336             }
    2337
    2338             public Object classData(Class<?> c) {
    2339                 return c.getClassData();
    2340             }
    2341         });
    2342     }
    2343 }
    --- EOF ---