第十一章 System类

System类有3个公开的静态常量:

  • out
    向标准输出流 写入信息
  • err
    向标准错误流中写入信息
  • in
    从标准输入流中读取信息
第十一章 System类_第1张图片
System源码

从注释可知,System类的初始化过程分为两个阶段。

  • 第一个阶段由类初始化方法完成,在这个方法中registerNatives()方法会注册
    其他本地方法。
  • 第二个阶段由VM完成,在这个阶段VM会调用System.initializeSystemClass()↓方法。
/**
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {
... // 其他代码
  FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
  FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
  FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
  setIn0(new BufferedInputStream(fdIn));
//本地方 入参是newPrintStream()结果
  setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
  setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
... // 其他代码
}

↑可见in、out和err正是在这里设置的
newPrintStream()方法↓

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

System.out常量是PrintStream类型,Java的io类库使用了装饰器模式,
它内部包装了一个BufferedOutputStream实例。BufferedOutputStream内部又包装了一个FileOutputStream实例。

调用System.out.println(String)方法之后,经过层层包装,最后到达
FileOutputStream类, 它是最里面的, 有个本地方法writeBytes()

// java.io.FileOutputStream
public class FileOutputStream extends OutputStream {
  
  //最终到这个本地方法
  private native void writeBytes(byte b[], int off, int len, boolean append)throws IOException;
}

VM

sun.misc.VM类的源代码(VM类属于Oracle私有代码,并没有开源,下面是反编译后
的Java代码):

// sun.misc.VM
public class VM {
  ... // 其他代码

  static {
    ... // 其他代码
    initialize();
  }

  private static native void initialize();
}

VM类在初始化时调用了initialize()方法。虽然initialize()是本
地方法,但是可以推测正是这个方法调用了System.initializeSystemClass()方法。

虚拟机在开始执行mian方法之前就会加载VM类,并初始化类, 里面的static块就会被执行

你可能感兴趣的:(第十一章 System类)