上次面試中遇到的一個問題,問到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