源码分析
/**
* The <code>System</code> class contains several useful class fields
* and methods. It cannot be instantiated.
*
* <p>Among the facilities provided by the <code>System</code> class
* are standard input, standard output, and error output streams;
* access to externally defined properties and environment
* variables; a means of loading files and libraries; and a utility
* method for quickly copying a portion of an array.
*
* @author unascribed
* @since JDK1.0
*/
public final class System {
// ***
}
System类包含一些有用的类的属性和方法,它不能被初始化。
在System类提供的工具主要是:标准输入,标准输出和错误输出流;访问外部定义的属性和环境变量;提供加载文件和库的一种手段;快速复制一个数组或部分数组的一个实用方法。
/** Don't let anyone instantiate this class */
private System() {
}
私有构造函数,用户不能初始化
/**
* The "standard" input stream. This stream is already
* open and ready to supply input data. Typically this stream
* corresponds to keyboard input or another input source specified by
* the host environment or user.
*/
public final static InputStream in = null;
标准输入流,这个流已经打开了而且随时准备着供给输入数据,一般这个流对应着键盘输入或其他主机环境或用户输入源
/**
* The "standard" output stream. This stream is already
* open and ready to accept output data. Typically this stream
* corresponds to display output or another output destination
* specified by the host environment or user.
* <p>
* For simple stand-alone Java applications, a typical way to write
* a line of output data is:
* <blockquote><pre>
* System.out.println(data)
* </pre></blockquote>
* <p>
* See the <code>println</code> methods in class <code>PrintStream</code>.
*
* @see java.io.PrintStream#println()
* @see java.io.PrintStream#println(boolean)
* @see java.io.PrintStream#println(char)
* @see java.io.PrintStream#println(char[])
* @see java.io.PrintStream#println(double)
* @see java.io.PrintStream#println(float)
* @see java.io.PrintStream#println(int)
* @see java.io.PrintStream#println(long)
* @see java.io.PrintStream#println(java.lang.Object)
* @see java.io.PrintStream#println(java.lang.String)
*/
public final static PrintStream out = null;
标准输出流,这个流是已经打开的,随时准备接收输出数据。一般这个流对应输出或其他主机环境或用户的输出目的。
/**
* The "standard" error output stream. This stream is already
* open and ready to accept output data.
*/
public final static PrintStream err = null;
标准错误输出流,这个流是已经打开的,随时准备接收去输出错误。
/**
* Returns the current time in milliseconds. Note that
* while the unit of time of the return value is a millisecond,
* the granularity of the value depends on the underlying
* operating system and may be larger. For example, many
* operating systems measure time in units of tens of
* milliseconds.
*
* <p> See the description of the class <code>Date</code> for
* a discussion of slight discrepancies that may arise between
* "computer time" and coordinated universal time (UTC).
*
* @return the difference, measured in milliseconds, between
* the current time and midnight, January 1, 1970 UTC.
* @see java.util.Date
*/
public static native long currentTimeMillis();
返回当前时间的毫秒值,是一个native方法。
/**
* Returns the current value of the running Java Virtual Machine's
* high-resolution time source, in nanoseconds.
*
* <p>This method can only be used to measure elapsed time and is
* not related to any other notion of system or wall-clock time.
* The value returned represents nanoseconds since some fixed but
* arbitrary <i>origin</i> time (perhaps in the future, so values
* may be negative). The same origin is used by all invocations of
* this method in an instance of a Java virtual machine; other
* virtual machine instances are likely to use a different origin.
*
* <p>This method provides nanosecond precision, but not necessarily
* nanosecond resolution (that is, how frequently the value changes)
* - no guarantees are made except that the resolution is at least as
* good as that of {@link #currentTimeMillis()}.
*
* <p>Differences in successive calls that span greater than
* approximately 292 years (2<sup>63</sup> nanoseconds) will not
* correctly compute elapsed time due to numerical overflow.
*
* <p>The values returned by this method become meaningful only when
* the difference between two such values, obtained within the same
* instance of a Java virtual machine, is computed.
*
* <p> For example, to measure how long some code takes to execute:
* <pre> {@code
* long startTime = System.nanoTime();
* // ... the code being measured ...
* long estimatedTime = System.nanoTime() - startTime;}</pre>
*
* <p>To compare two nanoTime values
* <pre> {@code
* long t0 = System.nanoTime();
* ...
* long t1 = System.nanoTime();}</pre>
*
* one should use {@code t1 - t0 < 0}, not {@code t1 < t0},
* because of the possibility of numerical overflow.
*
* @return the current value of the running Java Virtual Machine's
* high-resolution time source, in nanoseconds
* @since 1.5
*/
public static native long nanoTime();
返回当前运行的jvm的高精度时间源时间,单位是纳秒。也是一个native方法。
/**
* Copies an array from the specified source array, beginning at the
* specified position, to the specified position of the destination array.
* A subsequence of array components are copied from the source
* array referenced by <code>src</code> to the destination array
* referenced by <code>dest</code>. The number of components copied is
* equal to the <code>length</code> argument. The components at
* positions <code>srcPos</code> through
* <code>srcPos+length-1</code> in the source array are copied into
* positions <code>destPos</code> through
* <code>destPos+length-1</code>, respectively, of the destination
* array.
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
从源数组复制一个数组,从某一位置开始,到目的数组。
/**
* System properties. The following properties are guaranteed to be defined:
* <dl>
* <dt>java.version <dd>Java version number
* <dt>java.vendor <dd>Java vendor specific string
* <dt>java.vendor.url <dd>Java vendor URL
* <dt>java.home <dd>Java installation directory
* <dt>java.class.version <dd>Java class version number
* <dt>java.class.path <dd>Java classpath
* <dt>os.name <dd>Operating System Name
* <dt>os.arch <dd>Operating System Architecture
* <dt>os.version <dd>Operating System Version
* <dt>file.separator <dd>File separator ("/" on Unix)
* <dt>path.separator <dd>Path separator (":" on Unix)
* <dt>line.separator <dd>Line separator ("\n" on Unix)
* <dt>user.name <dd>User account name
* <dt>user.home <dd>User home directory
* <dt>user.dir <dd>User's current working directory
* </dl>
*/
private static Properties props;
private static native Properties initProperties(Properties props);
系统属性,上面罗列的属性可以被定义。
/**
* Determines the current system properties.
* <p>
* First, if there is a security manager, its
* <code>checkPropertiesAccess</code> method is called with no
* arguments. This may result in a security exception.
* <p>
* The current set of system properties for use by the
* {@link #getProperty(String)} method is returned as a
* <code>Properties</code> object. If there is no current set of
* system properties, a set of system properties is first created and
* initialized. This set of system properties always includes values
* for the following keys:
* <table summary="Shows property keys and associated values">
* <tr><th>Key</th>
* <th>Description of Associated Value</th></tr>
* <tr><td><code>java.version</code></td>
* <td>Java Runtime Environment version</td></tr>
* <tr><td><code>java.vendor</code></td>
* <td>Java Runtime Environment vendor</td></tr>
* <tr><td><code>java.vendor.url</code></td>
* <td>Java vendor URL</td></tr>
* <tr><td><code>java.home</code></td>
* <td>Java installation directory</td></tr>
* <tr><td><code>java.vm.specification.version</code></td>
* <td>Java Virtual Machine specification version</td></tr>
* <tr><td><code>java.vm.specification.vendor</code></td>
* <td>Java Virtual Machine specification vendor</td></tr>
* <tr><td><code>java.vm.specification.name</code></td>
* <td>Java Virtual Machine specification name</td></tr>
* <tr><td><code>java.vm.version</code></td>
* <td>Java Virtual Machine implementation version</td></tr>
* <tr><td><code>java.vm.vendor</code></td>
* <td>Java Virtual Machine implementation vendor</td></tr>
* <tr><td><code>java.vm.name</code></td>
* <td>Java Virtual Machine implementation name</td></tr>
* <tr><td><code>java.specification.version</code></td>
* <td>Java Runtime Environment specification version</td></tr>
* <tr><td><code>java.specification.vendor</code></td>
* <td>Java Runtime Environment specification vendor</td></tr>
* <tr><td><code>java.specification.name</code></td>
* <td>Java Runtime Environment specification name</td></tr>
* <tr><td><code>java.class.version</code></td>
* <td>Java class format version number</td></tr>
* <tr><td><code>java.class.path</code></td>
* <td>Java class path</td></tr>
* <tr><td><code>java.library.path</code></td>
* <td>List of paths to search when loading libraries</td></tr>
* <tr><td><code>java.io.tmpdir</code></td>
* <td>Default temp file path</td></tr>
* <tr><td><code>java.compiler</code></td>
* <td>Name of JIT compiler to use</td></tr>
* <tr><td><code>java.ext.dirs</code></td>
* <td>Path of extension directory or directories
* <b>Deprecated.</b> <i>This property, and the mechanism
* which implements it, may be removed in a future
* release.</i> </td></tr>
* <tr><td><code>os.name</code></td>
* <td>Operating system name</td></tr>
* <tr><td><code>os.arch</code></td>
* <td>Operating system architecture</td></tr>
* <tr><td><code>os.version</code></td>
* <td>Operating system version</td></tr>
* <tr><td><code>file.separator</code></td>
* <td>File separator ("/" on UNIX)</td></tr>
* <tr><td><code>path.separator</code></td>
* <td>Path separator (":" on UNIX)</td></tr>
* <tr><td><code>line.separator</code></td>
* <td>Line separator ("\n" on UNIX)</td></tr>
* <tr><td><code>user.name</code></td>
* <td>User's account name</td></tr>
* <tr><td><code>user.home</code></td>
* <td>User's home directory</td></tr>
* <tr><td><code>user.dir</code></td>
* <td>User's current working directory</td></tr>
* </table>
* <p>
* Multiple paths in a system property value are separated by the path
* separator character of the platform.
* <p>
* Note that even if the security manager does not permit the
* <code>getProperties</code> operation, it may choose to permit the
* {@link #getProperty(String)} operation.
*
* @return the system properties
* @exception SecurityException if a security manager exists and its
* <code>checkPropertiesAccess</code> method doesn't allow access
* to the system properties.
* @see #setProperties
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkPropertiesAccess()
* @see java.util.Properties
*/
public static Properties getProperties() {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
return props;
}
获得系统属性
/**
* Returns the system-dependent line separator string. It always
* returns the same value - the initial value of the {@linkplain
* #getProperty(String) system property} {@code line.separator}.
*
* <p>On UNIX systems, it returns {@code "\n"}; on Microsoft
* Windows systems it returns {@code "\r\n"}.
*
* @return the system-dependent line separator string
* @since 1.7
*/
public static String lineSeparator() {
return lineSeparator;
}
private static String lineSeparator;
获取行分隔符,如果是unix系统,就返回\n;如果是windows系统,则返回\r\n
/**
* Sets the system properties to the <code>Properties</code>
* argument.
* <p>
* First, if there is a security manager, its
* <code>checkPropertiesAccess</code> method is called with no
* arguments. This may result in a security exception.
* <p>
* The argument becomes the current set of system properties for use
* by the {@link #getProperty(String)} method. If the argument is
* <code>null</code>, then the current set of system properties is
* forgotten.
*
* @param props the new system properties.
* @exception SecurityException if a security manager exists and its
* <code>checkPropertiesAccess</code> method doesn't allow access
* to the system properties.
* @see #getProperties
* @see java.util.Properties
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkPropertiesAccess()
*/
public static void setProperties(Properties props) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
if (props == null) {
props = new Properties();
initProperties(props);
}
System.props = props;
}
设置某一系统属性
/**
* Gets the system property indicated by the specified key.
* <p>
* First, if there is a security manager, its
* <code>checkPropertyAccess</code> method is called with the key as
* its argument. This may result in a SecurityException.
* <p>
* If there is no current set of system properties, a set of system
* properties is first created and initialized in the same manner as
* for the <code>getProperties</code> method.
*
* @param key the name of the system property.
* @return the string value of the system property,
* or <code>null</code> if there is no property with that key.
*
* @exception SecurityException if a security manager exists and its
* <code>checkPropertyAccess</code> method doesn't allow
* access to the specified system property.
* @exception NullPointerException if <code>key</code> is
* <code>null</code>.
* @exception IllegalArgumentException if <code>key</code> is empty.
* @see #setProperty
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkPropertyAccess(java.lang.String)
* @see java.lang.System#getProperties()
*/
public static String getProperty(String key) {
checkKey(key);
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPropertyAccess(key);
}
return props.getProperty(key);
}
获取某一系统属性
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.equals("")) {
throw new IllegalArgumentException("key can't be empty");
}
}
校验key的值
public static String getenv(String name) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("getenv."+name));
}
return ProcessEnvironment.getenv(name);
}
获取指定的环境变量
public static void exit(int status) {
Runtime.getRuntime().exit(status);
}
退出当前运行的jvm
/**
* Runs the garbage collector.
* <p>
* Calling the <code>gc</code> method suggests that the Java Virtual
* Machine expend effort toward recycling unused objects in order to
* make the memory they currently occupy available for quick reuse.
* When control returns from the method call, the Java Virtual
* Machine has made a best effort to reclaim space from all discarded
* objects.
* <p>
* The call <code>System.gc()</code> is effectively equivalent to the
* call:
* <blockquote><pre>
* Runtime.getRuntime().gc()
* </pre></blockquote>
*
* @see java.lang.Runtime#gc()
*/
public static void gc() {
Runtime.getRuntime().gc();
}
手动调用垃圾回收方法
/**
* Loads the native library specified by the filename argument. The filename
* argument must be an absolute path name.
*
* If the filename argument, when stripped of any platform-specific library
* prefix, path, and file extension, indicates a library whose name is,
* for example, L, and a native library called L is statically linked
* with the VM, then the JNI_OnLoad_L function exported by the library
* is invoked rather than attempting to load a dynamic library.
* A filename matching the argument does not have to exist in the
* file system.
* See the JNI Specification for more details.
*
* Otherwise, the filename argument is mapped to a native library image in
* an implementation-dependent manner.
*
* <p>
* The call <code>System.load(name)</code> is effectively equivalent
* to the call:
* <blockquote><pre>
* Runtime.getRuntime().load(name)
* </pre></blockquote>
*
* @param filename the file to load.
* @exception SecurityException if a security manager exists and its
* <code>checkLink</code> method doesn't allow
* loading of the specified dynamic library
* @exception UnsatisfiedLinkError if either the filename is not an
* absolute path name, the native library is not statically
* linked with the VM, or the library cannot be mapped to
* a native library image by the host system.
* @exception NullPointerException if <code>filename</code> is
* <code>null</code>
* @see java.lang.Runtime#load(java.lang.String)
* @see java.lang.SecurityManager#checkLink(java.lang.String)
*/
@CallerSensitive
public static void load(String filename) {
Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
}
通过filename加载本地库
@CallerSensitive
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}
同上
/**
* Create PrintStream for stdout/err based on encoding.
*/
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);
}
通过编码创建stdout/err输出流
/**
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {
// VM might invoke JNU_NewStringPlatform() to set those encoding
// sensitive properties (user.home, user.name, boot.class.path, etc.)
// during "props" initialization, in which it may need access, via
// System.getProperty(), to the related system encoding property that
// have been initialized (put into "props") at early stage of the
// initialization. So make sure the "props" is available at the
// very beginning of the initialization and all system properties to
// be put into it directly.
props = new Properties();
initProperties(props); // initialized by the VM
// 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
// removed from the system properties.
//
// See java.lang.Integer.IntegerCache and the
// sun.misc.VM.saveAndRemoveProperties method for example.
//
// Save a private copy of the system properties object that
// can only be accessed by the internal implementation. Remove
// certain system properties that are not intended for public access.
sun.misc.VM.saveAndRemoveProperties(props);
lineSeparator = props.getProperty("line.separator");
sun.misc.Version.init();
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")));
// Load the zip library now in order to keep java.util.zip.ZipFile
// from trying to use itself to load this library later.
loadLibrary("zip");
// Setup Java signal handlers for HUP, TERM, and INT (where available).
Terminator.setup();
// Initialize any miscellenous 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.
sun.misc.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
// sun.misc.VM.isBooted() in order to avoid doing things that should
// wait until the application class loader has been set up.
// IMPORTANT: Ensure that this remains the last initialization action!
sun.misc.VM.booted();
}
初始化System类,线程初始化结束后调用。
初始化属性,初始化标准输入输出,初始化环境变量。