java io学习(十六) System.out.println("hello world")原理2014-08-12我们初学java的第一个程序是"hello world"1 public class HelloWorld {2 public static void main(String[] args) {3 System.out.println("hello world");4 }5 }上面程序到底是怎么在屏幕上输出“hello world”的呢?这就是本来要讲解的内容,即System.out.println("hello world")的原理。我们先看看System.out.println的流程。先看看System.java中out的定义,源码如下:
public final class System {... public final static PrintStream out = null; ...}从中,我们发现,(01) out是System.java的静态变量。(02) 而且out是PrintStream对象,PrintStream.java中有许多重载的println()方法。OK,我们知道了out是PrintStream对象。接下来,看它是如何被初始化的,它是怎么和屏幕输出关联的?我们还是一步步来分析,首先看看System.java的initializeSystemClass()方法。1. initializeSystemClass()的源码如下: 把out部分标记为红色
private static void initializeSystemClass() { props = new Properties();initProperties(props);// initialized by the VM 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(new PrintStream(new BufferedOutputStream(fdOut, 128), true));setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); loadLibrary("zip"); Terminator.setup(); sun.misc.VM.initializeOSEnvironment(); Thread current = Thread.currentThread();current.getThreadGroup().add(current); setJavaLangAccess(); sun.misc.VM.booted();}我们只需要关注上面的红色代码部分:即FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));将这两句话细分,可以划分为以下几步:第1步 FileDescriptor fd = FileDescriptor.out;第2步 FileOutputStream fdOut = new FileOutputStream(fd);第3步 BufferedOutputStream bufOut = new BufferedOutputStream(fdOut, 128);第4步 PrintStream ps = new PrintStream(bufout, true);第5步 setOut0(ps);说明:(01) 第1步,获取FileDescriptor.java中的静态成员out,out是一个FileDescriptor对象,它实际上是“标准输出(屏幕)”的标识符。关于FileDescriptor的详细介绍,可以参考博文“java io系列09之 FileDescriptor总结”。FileDescriptor.java中与FileDescriptor.out相关代码如下:
public final class FileDescriptor { private int fd; public static final FileDescriptor out = new FileDescriptor(1); private FileDescriptor(int fd) {this.fd = fd;useCount = new AtomicInteger();} ...}