java.lang.SystemクラスはJavaプログラマなら真っ先に使うクラスと言える。”Hello World”アプリケーションを書いたときに,「System.out.println(“Hello World!”);」と書いたはずだ。このコードの先頭にあるSystemが,java.lang.Systemクラスである。outはjava.lang.Systemクラスの中でpublicフィールドとして, public static final PrintStream out = null; と定義されており,java.io.PrintStream型である。System.inやSystem.errも同様の定義だ。
全体では2000行を超える大きなソースコードであるので,一部を抽出して引用する。
このほかにSystemクラスの中ではSecurityManagerの設定や,システムプロパティを設定する処理が定義されている。更にJava 9から,ログの設定までjava.lang.Systemクラスの中にインナークラス等として導入されている。ログの扱いは一つのまとまった機能であるので,独立したクラスとした方がよいようにも思えるが,なぜこのような実装になっているのかは不明である。
後半はシステムの初期化の処理が書かれている。コメントにはJava VMから呼び出されるという趣旨のメッセージが書かれている。Java VMはC言語で書かれているので,そこから直接呼ぶのであろう。
/*
* Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the “Classpath” exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Console;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.module.ModuleDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.nio.charset.CharacterCodingException;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.ResourceBundle;
import java.util.function.Supplier;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import jdk.internal.util.StaticProperty;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.ServicesCatalog;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.logger.LoggerFinderLoader;
import jdk.internal.logger.LazyLoggers;
import jdk.internal.logger.LocalizedLoggerWrapper;
import jdk.internal.util.SystemProps;
import jdk.internal.vm.annotation.Stable;
import sun.reflect.annotation.AnnotationType;
import sun.nio.ch.Interruptible;
import sun.security.util.SecurityConstants;
public final class System {
public static final InputStream in = null;
public static final PrintStream out = null;
public static final PrintStream err = null;
// indicates if a security manager is possible
private static final int NEVER = 1;
private static final int MAYBE = 2;
private static @Stable int allowSecurityManager;
// current security manager
private static volatile SecurityManager security; // read by VM
// return true if a security manager is allowed
private static boolean allowSecurityManager() {
return (allowSecurityManager != NEVER);
}
public static void setIn(InputStream in) {
checkIO();
setIn0(in);
}
public static void setOut(PrintStream out) {
checkIO();
setOut0(out);
}
public static void setErr(PrintStream err) {
checkIO();
setErr0(err);
}
private static volatile Console cons;
public static Console console() {
Console c;
if ((c = cons) == null) {
synchronized (System.class) {
if ((c = cons) == null) {
cons = c = SharedSecrets.getJavaIOAccess().console();
}
}
}
return c;
}
private static void checkIO() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“setIO”));
}
}
public static void setSecurityManager(SecurityManager sm) {
if (allowSecurityManager()) {
if (security == null) {
// ensure image reader is initialized
Object.class.getResource(“java/lang/ANY”);
}
if (sm != null) {
try {
// pre-populates the SecurityManager.packageAccess cache
// to avoid recursive permission checking issues with custom
// SecurityManager implementations
sm.checkPackageAccess(“java.lang”);
} catch (Exception e) {
// no-op
}
}
setSecurityManager0(sm);
} else {
// security manager not allowed
if (sm != null) {
throw new UnsupportedOperationException(
“Runtime configured to disallow security manager”);
}
}
}
private static synchronized
void setSecurityManager0(final SecurityManager s) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“setSecurityManager”));
}
if ((s != null) && (s.getClass().getClassLoader() != null)) {
AccessController.doPrivileged(new PrivilegedAction<>() {
public Object run() {
s.getClass().getProtectionDomain().implies
(SecurityConstants.ALL_PERMISSION);
return null;
}
});
}
security = s;
}
public static SecurityManager getSecurityManager() {
if (allowSecurityManager()) {
return security;
} else {
return null;
}
}
private static Properties props;
public static Properties getProperties() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
return props;
}
public static String lineSeparator() {
return lineSeparator;
}
private static String lineSeparator;
public static void setProperties(Properties props) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
if (props == null) {
Map<String, String> tempProps = SystemProps.initProperties();
VersionProps.init(tempProps);
props = createProperties(tempProps);
}
System.props = props;
}
public static String getProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key);
}
public static String getProperty(String key, String def) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key, def);
}
public static String setProperty(String key, String value) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new PropertyPermission(key,
SecurityConstants.PROPERTY_WRITE_ACTION));
}
return (String) props.setProperty(key, value);
}
public static String clearProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new PropertyPermission(key, “write”));
}
return (String) props.remove(key);
}
private static void checkKey(String key) {
if (key == null) {
throw new NullPointerException(“key can’t be null”);
}
if (key.isEmpty()) {
throw new IllegalArgumentException(“key can’t be empty”);
}
}
public static String getenv(String name) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“getenv.”+name));
}
return ProcessEnvironment.getenv(name);
}
public static java.util.Map<String,String> getenv() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“getenv.*”));
}
return ProcessEnvironment.getenv();
}
public interface Logger {
// 省略
}
public static abstract class LoggerFinder {
//省略
}
@CallerSensitive
public static Logger getLogger(String name) {
Objects.requireNonNull(name);
final Class<?> caller = Reflection.getCallerClass();
if (caller == null) {
throw new IllegalCallerException(“no caller frame”);
}
return LazyLoggers.getLogger(name, caller.getModule());
}
@CallerSensitive
public static Logger getLogger(String name, ResourceBundle bundle) {
final ResourceBundle rb = Objects.requireNonNull(bundle);
Objects.requireNonNull(name);
final Class<?> caller = Reflection.getCallerClass();
if (caller == null) {
throw new IllegalCallerException(“no caller frame”);
}
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
final PrivilegedAction<Logger> pa =
() -> LoggerFinder.accessProvider()
.getLocalizedLogger(name, rb, caller.getModule());
return AccessController.doPrivileged(pa, null,
LoggerFinder.LOGGERFINDER_PERMISSION);
}
return LoggerFinder.accessProvider()
.getLocalizedLogger(name, rb, caller.getModule());
}
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
public static void gc() {
Runtime.getRuntime().gc();
}
public static void runFinalization() {
Runtime.getRuntime().runFinalization();
}
@CallerSensitive
public static void load(String filename) {
Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
}
@CallerSensitive
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}
public static native String mapLibraryName(String libname);
private static PrintStream newPrintStream(FileOutputStream fos, String enc) {
if (enc != null) {
try {
return new PrintStream(new BufferedOutputStream(fos, 128), true, enc);
} catch (UnsupportedEncodingException uee) {}
}
return new PrintStream(new BufferedOutputStream(fos, 128), true);
}
private static void logInitException(boolean printToStderr,
boolean printStackTrace,
String msg,
Throwable e) {
if (VM.initLevel() < 1) {
throw new InternalError(“system classes not initialized”);
}
PrintStream log = (printToStderr) ? err : out;
if (msg != null) {
log.println(msg);
}
if (printStackTrace) {
e.printStackTrace(log);
} else {
log.println(e);
for (Throwable suppressed : e.getSuppressed()) {
log.println(“Suppressed: ” + suppressed);
}
Throwable cause = e.getCause();
if (cause != null) {
log.println(“Caused by: ” + cause);
}
}
}
private static Properties createProperties(Map<String, String> initialProps) {
Properties properties = new Properties(initialProps.size());
for (var entry : initialProps.entrySet()) {
String prop = entry.getKey();
switch (prop) {
// Do not add private system properties to the Properties
case “sun.nio.MaxDirectMemorySize”:
case “sun.nio.PageAlignDirectMemory”:
// used by java.lang.Integer.IntegerCache
case “java.lang.Integer.IntegerCache.high”:
// used by sun.launcher.LauncherHelper
case “sun.java.launcher.diag”:
// used by jdk.internal.loader.ClassLoaders
case “jdk.boot.class.path.append”:
break;
default:
properties.put(prop, entry.getValue());
}
}
return properties;
}
private static void initPhase1() {
// VM might invoke JNU_NewStringPlatform() to set those encoding
// sensitive properties (user.home, user.name, boot.class.path, etc.)
// during “props” initialization.
// The charset is initialized in System.c and does not depend on the Properties.
Map<String, String> tempProps = SystemProps.initProperties();
VersionProps.init(tempProps);
// There are certain system configurations that may be controlled by
// VM options such as the maximum amount of direct memory and
// Integer cache size used to support the object identity semantics
// of autoboxing. Typically, the library will obtain these values
// from the properties set by the VM. If the properties are for
// internal implementation use only, these properties should be
// masked from the system properties.
//
// Save a private copy of the system properties object that
// can only be accessed by the internal implementation.
VM.saveProperties(tempProps);
props = createProperties(tempProps);
StaticProperty.javaHome(); // Load StaticProperty to cache the property values
lineSeparator = props.getProperty(“line.separator”);
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty(“sun.stdout.encoding”)));
setErr0(newPrintStream(fdErr, props.getProperty(“sun.stderr.encoding”)));
// Setup Java signal handlers for HUP, TERM, and INT (where available).
Terminator.setup();
// Initialize any miscellaneous operating system settings that need to be
// set for the class libraries. Currently this is no-op everywhere except
// for Windows where the process-wide error mode is set before the java.io
// classes are used.
VM.initializeOSEnvironment();
// The main thread is not added to its thread group in the same
// way as other threads; we must do it ourselves here.
Thread current = Thread.currentThread();
current.getThreadGroup().add(current);
// register shared secrets
setJavaLangAccess();
// Subsystems that are invoked during initialization can invoke
// VM.isBooted() in order to avoid doing things that should
// wait until the VM is fully initialized. The initialization level
// is incremented from 0 to 1 here to indicate the first phase of
// initialization has completed.
// IMPORTANT: Ensure that this remains the last initialization action!
VM.initLevel(1);
}
// @see #initPhase2()
static ModuleLayer bootLayer;
/*
* Invoked by VM. Phase 2 module system initialization.
* Only classes in java.base can be loaded in this phase.
*
* @param printToStderr print exceptions to stderr rather than stdout
* @param printStackTrace print stack trace when exception occurs
*
* @return JNI_OK for success, JNI_ERR for failure
*/
private static int initPhase2(boolean printToStderr, boolean printStackTrace) {
try {
bootLayer = ModuleBootstrap.boot();
} catch (Exception | Error e) {
logInitException(printToStderr, printStackTrace,
“Error occurred during initialization of boot layer”, e);
return -1; // JNI_ERR
}
// module system initialized
VM.initLevel(2);
return 0; // JNI_OK
}
/*
* Invoked by VM. Phase 3 is the final system initialization:
* 1. set security manager
* 2. set system class loader
* 3. set TCCL
*
* This method must be called after the module system initialization.
* The security manager and system class loader may be a custom class from
* the application classpath or modulepath.
*/
private static void initPhase3() {
String smProp = System.getProperty(“java.security.manager”);
if (smProp != null) {
switch (smProp) {
case “disallow”:
allowSecurityManager = NEVER;
break;
case “allow”:
allowSecurityManager = MAYBE;
break;
case “”:
case “default”:
setSecurityManager(new SecurityManager());
allowSecurityManager = MAYBE;
break;
default:
try {
ClassLoader cl = ClassLoader.getBuiltinAppClassLoader();
Class<?> c = Class.forName(smProp, false, cl);
Constructor<?> ctor = c.getConstructor();
// Must be a public subclass of SecurityManager with
// a public no-arg constructor
if (!SecurityManager.class.isAssignableFrom(c) ||
!Modifier.isPublic(c.getModifiers()) ||
!Modifier.isPublic(ctor.getModifiers())) {
throw new Error(“Could not create SecurityManager: “
+ ctor.toString());
}
// custom security manager may be in non-exported package
ctor.setAccessible(true);
SecurityManager sm = (SecurityManager) ctor.newInstance();
setSecurityManager(sm);
} catch (Exception e) {
throw new InternalError(“Could not create SecurityManager”, e);
}
allowSecurityManager = MAYBE;
}
} else {
allowSecurityManager = MAYBE;
}
// initializing the system class loader
VM.initLevel(3);
// system class loader initialized
ClassLoader scl = ClassLoader.initSystemClassLoader();
// set TCCL
Thread.currentThread().setContextClassLoader(scl);
// system is fully initialized
VM.initLevel(4);
}
private static void setJavaLangAccess() {
// Allow privileged classes outside of java.lang
SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
public List<Method> getDeclaredPublicMethods(Class<?> klass, String name, Class<?>… parameterTypes) {
return klass.getDeclaredPublicMethods(name, parameterTypes);
}
public jdk.internal.reflect.ConstantPool getConstantPool(Class<?> klass) {
return klass.getConstantPool();
}
public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
return klass.casAnnotationType(oldType, newType);
}
public AnnotationType getAnnotationType(Class<?> klass) {
return klass.getAnnotationType();
}
public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) {
return klass.getDeclaredAnnotationMap();
}
public byte[] getRawClassAnnotations(Class<?> klass) {
return klass.getRawAnnotations();
}
public byte[] getRawClassTypeAnnotations(Class<?> klass) {
return klass.getRawTypeAnnotations();
}
public byte[] getRawExecutableTypeAnnotations(Executable executable) {
return Class.getExecutableTypeAnnotationBytes(executable);
}
public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) {
return klass.getEnumConstantsShared();
}
public void blockedOn(Interruptible b) {
Thread.blockedOn(b);
}
public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
Shutdown.add(slot, registerShutdownInProgress, hook);
}
public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) {
return new Thread(target, acc);
}
@SuppressWarnings(“deprecation”)
public void invokeFinalize(Object o) throws Throwable {
o.finalize();
}
public ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl) {
return cl.createOrGetClassLoaderValueMap();
}
public Class<?> defineClass(ClassLoader loader, String name, byte[] b, ProtectionDomain pd, String source) {
return ClassLoader.defineClass1(loader, name, b, 0, b.length, pd, source);
}
public Class<?> findBootstrapClassOrNull(ClassLoader cl, String name) {
return cl.findBootstrapClassOrNull(name);
}
public Package definePackage(ClassLoader cl, String name, Module module) {
return cl.definePackage(name, module);
}
public String fastUUID(long lsb, long msb) {
return Long.fastUUID(lsb, msb);
}
public void addNonExportedPackages(ModuleLayer layer) {
SecurityManager.addNonExportedPackages(layer);
}
public void invalidatePackageAccessCache() {
SecurityManager.invalidatePackageAccessCache();
}
public Module defineModule(ClassLoader loader,
ModuleDescriptor descriptor,
URI uri) {
return new Module(null, loader, descriptor, uri);
}
public Module defineUnnamedModule(ClassLoader loader) {
return new Module(loader);
}
public void addReads(Module m1, Module m2) {
m1.implAddReads(m2);
}
public void addReadsAllUnnamed(Module m) {
m.implAddReadsAllUnnamed();
}
public void addExports(Module m, String pn, Module other) {
m.implAddExports(pn, other);
}
public void addExportsToAllUnnamed(Module m, String pn) {
m.implAddExportsToAllUnnamed(pn);
}
public void addOpens(Module m, String pn, Module other) {
m.implAddOpens(pn, other);
}
public void addOpensToAllUnnamed(Module m, String pn) {
m.implAddOpensToAllUnnamed(pn);
}
public void addOpensToAllUnnamed(Module m, Iterator<String> packages) {
m.implAddOpensToAllUnnamed(packages);
}
public void addUses(Module m, Class<?> service) {
m.implAddUses(service);
}
public boolean isReflectivelyExported(Module m, String pn, Module other) {
return m.isReflectivelyExported(pn, other);
}
public boolean isReflectivelyOpened(Module m, String pn, Module other) {
return m.isReflectivelyOpened(pn, other);
}
public ServicesCatalog getServicesCatalog(ModuleLayer layer) {
return layer.getServicesCatalog();
}
public Stream<ModuleLayer> layers(ModuleLayer layer) {
return layer.layers();
}
public Stream<ModuleLayer> layers(ClassLoader loader) {
return ModuleLayer.layers(loader);
}
public String newStringNoRepl(byte[] bytes, Charset cs) throws CharacterCodingException {
return StringCoding.newStringNoRepl(bytes, cs);
}
public byte[] getBytesNoRepl(String s, Charset cs) throws CharacterCodingException {
return StringCoding.getBytesNoRepl(s, cs);
}
public String newStringUTF8NoRepl(byte[] bytes, int off, int len) {
return StringCoding.newStringUTF8NoRepl(bytes, off, len);
}
public byte[] getBytesUTF8NoRepl(String s) {
return StringCoding.getBytesUTF8NoRepl(s);
}
public void setCause(Throwable t, Throwable cause) {
t.setCause(cause);
}
});
}
}
* Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the “Classpath” exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Console;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.module.ModuleDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URI;
import java.nio.charset.CharacterCodingException;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.nio.channels.Channel;
import java.nio.channels.spi.SelectorProvider;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.ResourceBundle;
import java.util.function.Supplier;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import jdk.internal.util.StaticProperty;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.ServicesCatalog;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.logger.LoggerFinderLoader;
import jdk.internal.logger.LazyLoggers;
import jdk.internal.logger.LocalizedLoggerWrapper;
import jdk.internal.util.SystemProps;
import jdk.internal.vm.annotation.Stable;
import sun.reflect.annotation.AnnotationType;
import sun.nio.ch.Interruptible;
import sun.security.util.SecurityConstants;
public final class System {
public static final InputStream in = null;
public static final PrintStream out = null;
public static final PrintStream err = null;
// indicates if a security manager is possible
private static final int NEVER = 1;
private static final int MAYBE = 2;
private static @Stable int allowSecurityManager;
// current security manager
private static volatile SecurityManager security; // read by VM
// return true if a security manager is allowed
private static boolean allowSecurityManager() {
return (allowSecurityManager != NEVER);
}
public static void setIn(InputStream in) {
checkIO();
setIn0(in);
}
public static void setOut(PrintStream out) {
checkIO();
setOut0(out);
}
public static void setErr(PrintStream err) {
checkIO();
setErr0(err);
}
private static volatile Console cons;
public static Console console() {
Console c;
if ((c = cons) == null) {
synchronized (System.class) {
if ((c = cons) == null) {
cons = c = SharedSecrets.getJavaIOAccess().console();
}
}
}
return c;
}
private static void checkIO() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“setIO”));
}
}
public static void setSecurityManager(SecurityManager sm) {
if (allowSecurityManager()) {
if (security == null) {
// ensure image reader is initialized
Object.class.getResource(“java/lang/ANY”);
}
if (sm != null) {
try {
// pre-populates the SecurityManager.packageAccess cache
// to avoid recursive permission checking issues with custom
// SecurityManager implementations
sm.checkPackageAccess(“java.lang”);
} catch (Exception e) {
// no-op
}
}
setSecurityManager0(sm);
} else {
// security manager not allowed
if (sm != null) {
throw new UnsupportedOperationException(
“Runtime configured to disallow security manager”);
}
}
}
private static synchronized
void setSecurityManager0(final SecurityManager s) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“setSecurityManager”));
}
if ((s != null) && (s.getClass().getClassLoader() != null)) {
AccessController.doPrivileged(new PrivilegedAction<>() {
public Object run() {
s.getClass().getProtectionDomain().implies
(SecurityConstants.ALL_PERMISSION);
return null;
}
});
}
security = s;
}
public static SecurityManager getSecurityManager() {
if (allowSecurityManager()) {
return security;
} else {
return null;
}
}
private static Properties props;
public static Properties getProperties() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
return props;
}
public static String lineSeparator() {
return lineSeparator;
}
private static String lineSeparator;
public static void setProperties(Properties props) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
if (props == null) {
Map<String, String> tempProps = SystemProps.initProperties();
VersionProps.init(tempProps);
props = createProperties(tempProps);
}
System.props = props;
}
public static String getProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key);
}
public static String getProperty(String key, String def) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key, def);
}
public static String setProperty(String key, String value) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new PropertyPermission(key,
SecurityConstants.PROPERTY_WRITE_ACTION));
}
return (String) props.setProperty(key, value);
}
public static String clearProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new PropertyPermission(key, “write”));
}
return (String) props.remove(key);
}
private static void checkKey(String key) {
if (key == null) {
throw new NullPointerException(“key can’t be null”);
}
if (key.isEmpty()) {
throw new IllegalArgumentException(“key can’t be empty”);
}
}
public static String getenv(String name) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“getenv.”+name));
}
return ProcessEnvironment.getenv(name);
}
public static java.util.Map<String,String> getenv() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission(“getenv.*”));
}
return ProcessEnvironment.getenv();
}
public interface Logger {
// 省略
}
public static abstract class LoggerFinder {
//省略
}
@CallerSensitive
public static Logger getLogger(String name) {
Objects.requireNonNull(name);
final Class<?> caller = Reflection.getCallerClass();
if (caller == null) {
throw new IllegalCallerException(“no caller frame”);
}
return LazyLoggers.getLogger(name, caller.getModule());
}
@CallerSensitive
public static Logger getLogger(String name, ResourceBundle bundle) {
final ResourceBundle rb = Objects.requireNonNull(bundle);
Objects.requireNonNull(name);
final Class<?> caller = Reflection.getCallerClass();
if (caller == null) {
throw new IllegalCallerException(“no caller frame”);
}
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
final PrivilegedAction<Logger> pa =
() -> LoggerFinder.accessProvider()
.getLocalizedLogger(name, rb, caller.getModule());
return AccessController.doPrivileged(pa, null,
LoggerFinder.LOGGERFINDER_PERMISSION);
}
return LoggerFinder.accessProvider()
.getLocalizedLogger(name, rb, caller.getModule());
}
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
public static void gc() {
Runtime.getRuntime().gc();
}
public static void runFinalization() {
Runtime.getRuntime().runFinalization();
}
@CallerSensitive
public static void load(String filename) {
Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
}
@CallerSensitive
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}
public static native String mapLibraryName(String libname);
private static PrintStream newPrintStream(FileOutputStream fos, String enc) {
if (enc != null) {
try {
return new PrintStream(new BufferedOutputStream(fos, 128), true, enc);
} catch (UnsupportedEncodingException uee) {}
}
return new PrintStream(new BufferedOutputStream(fos, 128), true);
}
private static void logInitException(boolean printToStderr,
boolean printStackTrace,
String msg,
Throwable e) {
if (VM.initLevel() < 1) {
throw new InternalError(“system classes not initialized”);
}
PrintStream log = (printToStderr) ? err : out;
if (msg != null) {
log.println(msg);
}
if (printStackTrace) {
e.printStackTrace(log);
} else {
log.println(e);
for (Throwable suppressed : e.getSuppressed()) {
log.println(“Suppressed: ” + suppressed);
}
Throwable cause = e.getCause();
if (cause != null) {
log.println(“Caused by: ” + cause);
}
}
}
private static Properties createProperties(Map<String, String> initialProps) {
Properties properties = new Properties(initialProps.size());
for (var entry : initialProps.entrySet()) {
String prop = entry.getKey();
switch (prop) {
// Do not add private system properties to the Properties
case “sun.nio.MaxDirectMemorySize”:
case “sun.nio.PageAlignDirectMemory”:
// used by java.lang.Integer.IntegerCache
case “java.lang.Integer.IntegerCache.high”:
// used by sun.launcher.LauncherHelper
case “sun.java.launcher.diag”:
// used by jdk.internal.loader.ClassLoaders
case “jdk.boot.class.path.append”:
break;
default:
properties.put(prop, entry.getValue());
}
}
return properties;
}
private static void initPhase1() {
// VM might invoke JNU_NewStringPlatform() to set those encoding
// sensitive properties (user.home, user.name, boot.class.path, etc.)
// during “props” initialization.
// The charset is initialized in System.c and does not depend on the Properties.
Map<String, String> tempProps = SystemProps.initProperties();
VersionProps.init(tempProps);
// There are certain system configurations that may be controlled by
// VM options such as the maximum amount of direct memory and
// Integer cache size used to support the object identity semantics
// of autoboxing. Typically, the library will obtain these values
// from the properties set by the VM. If the properties are for
// internal implementation use only, these properties should be
// masked from the system properties.
//
// Save a private copy of the system properties object that
// can only be accessed by the internal implementation.
VM.saveProperties(tempProps);
props = createProperties(tempProps);
StaticProperty.javaHome(); // Load StaticProperty to cache the property values
lineSeparator = props.getProperty(“line.separator”);
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty(“sun.stdout.encoding”)));
setErr0(newPrintStream(fdErr, props.getProperty(“sun.stderr.encoding”)));
// Setup Java signal handlers for HUP, TERM, and INT (where available).
Terminator.setup();
// Initialize any miscellaneous operating system settings that need to be
// set for the class libraries. Currently this is no-op everywhere except
// for Windows where the process-wide error mode is set before the java.io
// classes are used.
VM.initializeOSEnvironment();
// The main thread is not added to its thread group in the same
// way as other threads; we must do it ourselves here.
Thread current = Thread.currentThread();
current.getThreadGroup().add(current);
// register shared secrets
setJavaLangAccess();
// Subsystems that are invoked during initialization can invoke
// VM.isBooted() in order to avoid doing things that should
// wait until the VM is fully initialized. The initialization level
// is incremented from 0 to 1 here to indicate the first phase of
// initialization has completed.
// IMPORTANT: Ensure that this remains the last initialization action!
VM.initLevel(1);
}
// @see #initPhase2()
static ModuleLayer bootLayer;
/*
* Invoked by VM. Phase 2 module system initialization.
* Only classes in java.base can be loaded in this phase.
*
* @param printToStderr print exceptions to stderr rather than stdout
* @param printStackTrace print stack trace when exception occurs
*
* @return JNI_OK for success, JNI_ERR for failure
*/
private static int initPhase2(boolean printToStderr, boolean printStackTrace) {
try {
bootLayer = ModuleBootstrap.boot();
} catch (Exception | Error e) {
logInitException(printToStderr, printStackTrace,
“Error occurred during initialization of boot layer”, e);
return -1; // JNI_ERR
}
// module system initialized
VM.initLevel(2);
return 0; // JNI_OK
}
/*
* Invoked by VM. Phase 3 is the final system initialization:
* 1. set security manager
* 2. set system class loader
* 3. set TCCL
*
* This method must be called after the module system initialization.
* The security manager and system class loader may be a custom class from
* the application classpath or modulepath.
*/
private static void initPhase3() {
String smProp = System.getProperty(“java.security.manager”);
if (smProp != null) {
switch (smProp) {
case “disallow”:
allowSecurityManager = NEVER;
break;
case “allow”:
allowSecurityManager = MAYBE;
break;
case “”:
case “default”:
setSecurityManager(new SecurityManager());
allowSecurityManager = MAYBE;
break;
default:
try {
ClassLoader cl = ClassLoader.getBuiltinAppClassLoader();
Class<?> c = Class.forName(smProp, false, cl);
Constructor<?> ctor = c.getConstructor();
// Must be a public subclass of SecurityManager with
// a public no-arg constructor
if (!SecurityManager.class.isAssignableFrom(c) ||
!Modifier.isPublic(c.getModifiers()) ||
!Modifier.isPublic(ctor.getModifiers())) {
throw new Error(“Could not create SecurityManager: “
+ ctor.toString());
}
// custom security manager may be in non-exported package
ctor.setAccessible(true);
SecurityManager sm = (SecurityManager) ctor.newInstance();
setSecurityManager(sm);
} catch (Exception e) {
throw new InternalError(“Could not create SecurityManager”, e);
}
allowSecurityManager = MAYBE;
}
} else {
allowSecurityManager = MAYBE;
}
// initializing the system class loader
VM.initLevel(3);
// system class loader initialized
ClassLoader scl = ClassLoader.initSystemClassLoader();
// set TCCL
Thread.currentThread().setContextClassLoader(scl);
// system is fully initialized
VM.initLevel(4);
}
private static void setJavaLangAccess() {
// Allow privileged classes outside of java.lang
SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
public List<Method> getDeclaredPublicMethods(Class<?> klass, String name, Class<?>… parameterTypes) {
return klass.getDeclaredPublicMethods(name, parameterTypes);
}
public jdk.internal.reflect.ConstantPool getConstantPool(Class<?> klass) {
return klass.getConstantPool();
}
public boolean casAnnotationType(Class<?> klass, AnnotationType oldType, AnnotationType newType) {
return klass.casAnnotationType(oldType, newType);
}
public AnnotationType getAnnotationType(Class<?> klass) {
return klass.getAnnotationType();
}
public Map<Class<? extends Annotation>, Annotation> getDeclaredAnnotationMap(Class<?> klass) {
return klass.getDeclaredAnnotationMap();
}
public byte[] getRawClassAnnotations(Class<?> klass) {
return klass.getRawAnnotations();
}
public byte[] getRawClassTypeAnnotations(Class<?> klass) {
return klass.getRawTypeAnnotations();
}
public byte[] getRawExecutableTypeAnnotations(Executable executable) {
return Class.getExecutableTypeAnnotationBytes(executable);
}
public <E extends Enum<E>>
E[] getEnumConstantsShared(Class<E> klass) {
return klass.getEnumConstantsShared();
}
public void blockedOn(Interruptible b) {
Thread.blockedOn(b);
}
public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) {
Shutdown.add(slot, registerShutdownInProgress, hook);
}
public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) {
return new Thread(target, acc);
}
@SuppressWarnings(“deprecation”)
public void invokeFinalize(Object o) throws Throwable {
o.finalize();
}
public ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl) {
return cl.createOrGetClassLoaderValueMap();
}
public Class<?> defineClass(ClassLoader loader, String name, byte[] b, ProtectionDomain pd, String source) {
return ClassLoader.defineClass1(loader, name, b, 0, b.length, pd, source);
}
public Class<?> findBootstrapClassOrNull(ClassLoader cl, String name) {
return cl.findBootstrapClassOrNull(name);
}
public Package definePackage(ClassLoader cl, String name, Module module) {
return cl.definePackage(name, module);
}
public String fastUUID(long lsb, long msb) {
return Long.fastUUID(lsb, msb);
}
public void addNonExportedPackages(ModuleLayer layer) {
SecurityManager.addNonExportedPackages(layer);
}
public void invalidatePackageAccessCache() {
SecurityManager.invalidatePackageAccessCache();
}
public Module defineModule(ClassLoader loader,
ModuleDescriptor descriptor,
URI uri) {
return new Module(null, loader, descriptor, uri);
}
public Module defineUnnamedModule(ClassLoader loader) {
return new Module(loader);
}
public void addReads(Module m1, Module m2) {
m1.implAddReads(m2);
}
public void addReadsAllUnnamed(Module m) {
m.implAddReadsAllUnnamed();
}
public void addExports(Module m, String pn, Module other) {
m.implAddExports(pn, other);
}
public void addExportsToAllUnnamed(Module m, String pn) {
m.implAddExportsToAllUnnamed(pn);
}
public void addOpens(Module m, String pn, Module other) {
m.implAddOpens(pn, other);
}
public void addOpensToAllUnnamed(Module m, String pn) {
m.implAddOpensToAllUnnamed(pn);
}
public void addOpensToAllUnnamed(Module m, Iterator<String> packages) {
m.implAddOpensToAllUnnamed(packages);
}
public void addUses(Module m, Class<?> service) {
m.implAddUses(service);
}
public boolean isReflectivelyExported(Module m, String pn, Module other) {
return m.isReflectivelyExported(pn, other);
}
public boolean isReflectivelyOpened(Module m, String pn, Module other) {
return m.isReflectivelyOpened(pn, other);
}
public ServicesCatalog getServicesCatalog(ModuleLayer layer) {
return layer.getServicesCatalog();
}
public Stream<ModuleLayer> layers(ModuleLayer layer) {
return layer.layers();
}
public Stream<ModuleLayer> layers(ClassLoader loader) {
return ModuleLayer.layers(loader);
}
public String newStringNoRepl(byte[] bytes, Charset cs) throws CharacterCodingException {
return StringCoding.newStringNoRepl(bytes, cs);
}
public byte[] getBytesNoRepl(String s, Charset cs) throws CharacterCodingException {
return StringCoding.getBytesNoRepl(s, cs);
}
public String newStringUTF8NoRepl(byte[] bytes, int off, int len) {
return StringCoding.newStringUTF8NoRepl(bytes, off, len);
}
public byte[] getBytesUTF8NoRepl(String s) {
return StringCoding.getBytesUTF8NoRepl(s);
}
public void setCause(Throwable t, Throwable cause) {
t.setCause(cause);
}
});
}
}