上次面试中遇到的一个问题,问到System.out.println()中的out是否是内部类【不是内部类】,当时就给问蒙了,直观感受out应该是System类的一个属性,跟内部类有什么关系?并且以前整理IO部分的时候记得有个PrintStream的类用于标准输出的,可是从没看过System的源码,也不敢随便再说了。后来看了下源码,发现的确是PrintStream,可能当时想问的是内部类的用法吧(真心感受面试待靠缘分,不少面试官喜欢引导着问问题,方式很好,但不少时候可能让面试者搞不清你到底想问什么,我此次面试就深受打击,到最后面试官每一个问题我都要先想半天是否是留了什么坑),不过归根结底本身水平差得多,仍是要认真学习。 言归正传,System类是jdk提供的一个工具类,有final修饰,不可继承,由名字能够看出来,其中的操做多数和系统相关。其功能主要以下:java
一些jvm操做,如gc()、runFinalization()、exit(),该部分并未在源码的java doc中提到,可能由于自己不建议主动调用吧。并且这几个方法都仅仅是Runtime.getRuntime()的调用,二者没有区别 下边直接看图,主要的方法和功能都已经列出来。 面试
下边咱们重点来该类是如何初始化的。 首先在开头咱们就能够看以下代码:数组
private static native void registerNatives(); static { registerNatives(); }
类中的静态代码块调用了一个native方法registerNatives(),能够猜到该方法应该是一个入口方法,看一下注释:经过静态初始化注册native方法,该方法会令vm经过调用initializeSystemClass方法来完成初始化工做。果真如此,那么接下来咱们看下initializeSystemClass方法吧:app
private static void initializeSystemClass() { // 初始化props props = new Properties(); initProperties(props); sun.misc.VM.saveAndRemoveProperties(props); //获取系统相关的换行符 lineSeparator = props.getProperty("line.separator"); sun.misc.Version.init(); //分别建立in、out、err的实例对象,并经过setXX0()初始化,查看setXX0()方法可知,这是个native方法,将系统的标准流管理到类内的对象 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)); //加载zip包以获取java.util.zip.ZipFile这个类,以便以后加载利库使用 loadLibrary("zip"); // 设置平台相关的信号处理 Terminator.setup(); // 初始化sun.misc相关的环境变量 sun.misc.VM.initializeOSEnvironment(); // 主线程不会在同一个线程组中添加相同的线程,咱们必须在这里本身实现。注释半天没弄明白,看代码就是主线程本身把本身加到了本身的线程组中...... Thread current = Thread.currentThread(); current.getThreadGroup().add(current); // 注册共享秘钥?注释没看明白,该方法就是实例化一个JavaLangAccess setJavaLangAccess(); // 子系统在初始化的时候能够调用sun.misc.VM.isBooted(),以保证在application类加载器启动前不作任何事。booted()其实就是改了个状态,使isBooted()变为true。 sun.misc.VM.booted(); }
至此,System基本上便讲完了,不过还有不少底层的东西没看懂(setJavaLangAccess()),留待之后解决吧。jvm