System类构造函数由private修饰,不可以被实例化,加载时调用static代码块。

System类提供了标准输入输出流,错误输出流,获取外部属性和系统环境的方法,加载类库和文件的方法,快速copy数组的方法;其中out和err的类型是PrintStream

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

    /* register the natives via the static initializer.
     *
     * VM will invoke the initializeSystemClass method to complete
     * the initialization for this class separated from clinit.
     * Note that to use properties set by the VM, see the constraints
     * described in the initializeSystemClass method.
     */
    private static native void registerNatives();
    static {
        registerNatives();
    }

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

System.exit(int),终止当前虚拟机的运行,什么叫做当前虚拟机呢?

public static void exit(int status) {
        Runtime.getRuntime().exit(status);
    }

如果在某个线程中调用了exit会怎样?下面的例子输出结果是hello,把子线程和主线程的内容交换也是一样的结果。就是说不管在哪个线程调用了exit,整个应用都退出了。

package com.ysdx.test;

public class JavaTest {

    public static void main(String[] args) {

        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("hello!");
            System.exit(1);
        });

        thread.start();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Hello from main thread!");
    }
}

 两个虚拟机之间是互不影响的

其中JavaTest1如下

public class JavaTest1 {

    public static void main(String[] args) {

        

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Hello from main thread!");
    }
}

---------------------

System中gc相关操作

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

    /**
     * Runs the finalization methods of any objects pending finalization.
     * <p>
     * Calling this method suggests that the Java Virtual Machine expend
     * effort toward running the <code>finalize</code> methods of objects
     * that have been found to be discarded but whose <code>finalize</code>
     * methods have not yet been run. When control returns from the
     * method call, the Java Virtual Machine has made a best effort to
     * complete all outstanding finalizations.
     * <p>
     * The call <code>System.runFinalization()</code> is effectively
     * equivalent to the call:
     * <blockquote><pre>
     * Runtime.getRuntime().runFinalization()
     * </pre></blockquote>
     *
     * @see     java.lang.Runtime#runFinalization()
     */
    public static void runFinalization() {
        Runtime.getRuntime().runFinalization();
    }

 顺便看一下Runtime,

即便不显示调用gc,JVM也会自动在一个单独的线程中执行recycling process;

即便不显示调用runFinalization,JVM也会自动在一个单独的线程中执行finalization process;

可以很明显的看出gc和runFinalization是不同的,一个叫做回收过程,一个叫做终结过程。

调用runFinalization后,终结过程会调用已经被废弃但是尚未调用其finalization方法的对象。

函数注释里的描述都使用了suggest和has made its best effort,可能这两个函数还有不足之处。

/**
     * Runs the garbage collector.
     * Calling this 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 virtual machine has made
     * its best effort to recycle all discarded objects.
     * <p>
     * The name <code>gc</code> stands for "garbage
     * collector". The virtual machine performs this recycling
     * process automatically as needed, in a separate thread, even if the
     * <code>gc</code> method is not invoked explicitly.
     * <p>
     * The method {@link System#gc()} is the conventional and convenient
     * means of invoking this method.
     */
    public native void gc();

    /* Wormhole for calling java.lang.ref.Finalizer.runFinalization */
    private static native void runFinalization0();

    /**
     * Runs the finalization methods of any objects pending finalization.
     * Calling this method suggests that the Java virtual machine expend
     * effort toward running the <code>finalize</code> methods of objects
     * that have been found to be discarded but whose <code>finalize</code>
     * methods have not yet been run. When control returns from the
     * method call, the virtual machine has made a best effort to
     * complete all outstanding finalizations.
     * <p>
     * The virtual machine performs the finalization process
     * automatically as needed, in a separate thread, if the
     * <code>runFinalization</code> method is not invoked explicitly.
     * <p>
     * The method {@link System#runFinalization()} is the conventional
     * and convenient means of invoking this method.
     *
     * @see     java.lang.Object#finalize()
     */
    public void runFinalization() {
        runFinalization0();
    }

System中获取系统变量的方法:

getenv(String name)返回跟name对应的变量值;

getenv(),这个函数返回一个不可修改的、包含系统变量名和对应值的map,这个map在ProcessEnvironment中声明:private static final Map<String,String> theUnmodifiableEnvironment;

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

System类关于系统属性的操作有get、set和clear方法,而Environment只有读取的函数。

environment是操作系统环境变量信息,property感觉更像是jvm相关参数。下面例子的输出结果是:

java.runtime.name = Java(TM) SE Runtime Environment
sun.boot.library.path = C:\Program Files\Java\jre1.8.0_121\bin
java.vm.version = 25.121-b13
java.vm.vendor = Oracle Corporation
java.vendor.url = http://java.oracle.com/
path.separator = ;
java.vm.name = Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg = sun.io
user.script = 
user.country = CN
sun.java.launcher = SUN_STANDARD
sun.os.patch.level = 
java.vm.specification.name = Java Virtual Machine Specification
user.dir = F:\CodingSource\neon-workspace\JavaSystem
java.runtime.version = 1.8.0_121-b13
java.awt.graphicsenv = sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs = C:\Program Files\Java\jre1.8.0_121\lib\endorsed
os.arch = amd64
java.io.tmpdir = C:\Users\ADMINI~1\AppData\Local\Temp\
line.separator = 

java.vm.specification.vendor = Oracle Corporation
user.variant = 
os.name = Windows 8
sun.jnu.encoding = GBK
java.library.path = C:\Program Files\Java\jre1.8.0_121\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files/Java/jre1.8.0_121/bin/server;C:/Program Files/Java/jre1.8.0_121/bin;C:/Program Files/Java/jre1.8.0_121/lib/amd64;E:\CodingIDE\Python36\Scripts\;E:\CodingIDE\Python36\;E:\CodingIDE\DataBase\oraclexe\app\oracle\product\11.2.0\server\bin;;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Java\jdk1.8.0_121\bin;C:\Program Files\Java\jdk1.8.0_121\jre\bin;E:\CodingIDE\DataBase\mysql-5.7.17-winx64\bin;E:\CodingIDE\eclipse-jee-neon-3-RC3-win32-x86_64\eclipse;;.
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 6.2
user.home = C:\Users\Administrator
user.timezone = 
java.awt.printerjob = sun.awt.windows.WPrinterJob
file.encoding = GBK
java.specification.version = 1.8
user.name = Administrator
java.class.path = F:\CodingSource\neon-workspace\JavaSystem\bin
java.vm.specification.version = 1.8
sun.arch.data.model = 64
java.home = C:\Program Files\Java\jre1.8.0_121
sun.java.command = com.ysdx.jsys.JavaSystem
java.specification.vendor = Oracle Corporation
user.language = zh
awt.toolkit = sun.awt.windows.WToolkit
java.vm.info = mixed mode
java.version = 1.8.0_121
java.ext.dirs = C:\Program Files\Java\jre1.8.0_121\lib\ext;C:\Windows\Sun\Java\lib\ext
sun.boot.class.path = C:\Program Files\Java\jre1.8.0_121\lib\resources.jar;C:\Program Files\Java\jre1.8.0_121\lib\rt.jar;C:\Program Files\Java\jre1.8.0_121\lib\sunrsasign.jar;C:\Program Files\Java\jre1.8.0_121\lib\jsse.jar;C:\Program Files\Java\jre1.8.0_121\lib\jce.jar;C:\Program Files\Java\jre1.8.0_121\lib\charsets.jar;C:\Program Files\Java\jre1.8.0_121\lib\jfr.jar;C:\Program Files\Java\jre1.8.0_121\classes
java.vendor = Oracle Corporation
file.separator = \
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.cpu.endian = little
sun.io.unicode.encoding = UnicodeLittle
sun.desktop = windows
sun.cpu.isalist = amd64
-----------------------------------
USERDOMAIN_ROAMINGPROFILE=PC-201703120850
LOCALAPPDATA=C:\Users\Administrator\AppData\Local
PROCESSOR_LEVEL=6
FP_NO_HOST_CHECK=NO
USERDOMAIN=PC-201703120850
LOGONSERVER=\\PC-201703120850
JAVA_HOME=C:\Program Files\Java\jdk1.8.0_121
SESSIONNAME=Console
ALLUSERSPROFILE=C:\ProgramData
PROCESSOR_ARCHITECTURE=AMD64
PSModulePath=C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
#envTSLOGSHELLEXT3464=510784384
SystemDrive=C:
=C:=C:\
APPDATA=C:\Users\Administrator\AppData\Roaming
USERNAME=Administrator
ProgramFiles(x86)=C:\Program Files (x86)
VBOX_MSI_INSTALL_PATH=F:\VirtualBox\
CommonProgramFiles=C:\Program Files\Common Files
Path=C:/Program Files/Java/jre1.8.0_121/bin/server;C:/Program Files/Java/jre1.8.0_121/bin;C:/Program Files/Java/jre1.8.0_121/lib/amd64;E:\CodingIDE\Python36\Scripts\;E:\CodingIDE\Python36\;E:\CodingIDE\DataBase\oraclexe\app\oracle\product\11.2.0\server\bin;;C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Java\jdk1.8.0_121\bin;C:\Program Files\Java\jdk1.8.0_121\jre\bin;E:\CodingIDE\DataBase\mysql-5.7.17-winx64\bin;E:\CodingIDE\eclipse-jee-neon-3-RC3-win32-x86_64\eclipse;
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW
OS=Windows_NT
COMPUTERNAME=PC-201703120850
PROCESSOR_REVISION=3a09
CommonProgramW6432=C:\Program Files\Common Files
#envTSLOGsss3464=166647136
ComSpec=C:\Windows\system32\cmd.exe
#envTSLOGXMediaLibrary3464=166645216
ProgramData=C:\ProgramData
=F:=F:\
ProgramW6432=C:\Program Files
HOMEPATH=\Users\Administrator
SystemRoot=C:\Windows
TEMP=C:\Users\ADMINI~1\AppData\Local\Temp
HOMEDRIVE=C:
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
USERPROFILE=C:\Users\Administrator
TMP=C:\Users\ADMINI~1\AppData\Local\Temp
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
ProgramFiles=C:\Program Files
PUBLIC=C:\Users\Public
NUMBER_OF_PROCESSORS=4
windir=C:\Windows
#envTSLOGTSLOG3464=166646496
=::=::\

  

package com.ysdx.jsys;

import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;

public class JavaSystem {

    public static void main(String[] args) {
        Properties properties = System.getProperties();
        Enumeration<?> propertyNames = properties.propertyNames();
        for (; propertyNames.hasMoreElements();) {
            String propertyName = (String) propertyNames.nextElement();
            System.out.println(propertyName + " = " + properties.getProperty(propertyName));
        }
        System.out.println("-----------------------------------");
        Map<String, String> map = System.getenv();
        for (String key : map.keySet()) {
            System.out.println(key + "=" + map.get(key));

        }
    }

}