java十分鐘速懂知識點——System類

文章轉載自:http://www.cnblogs.com/good-temper/p/5042058.html?utm_source=tuicool&utm_medium=referral


上次面試中遇到的一個問題,問到System.out.println()中的out是不是內部類,當時就給問蒙了,直觀感覺out應該是System類的一個屬性,跟內部類有什麼關係?而且之前整理IO部分的時候記得有個PrintStream的類用於標準輸出的,但是從沒看過System的源碼,也不敢隨便再說了。後來看了下源碼,發現的確是PrintStream,可能當時想問的是內部類的用法吧(真心感覺面試待靠緣分,很多面試官喜歡引導着問問題,方式很好,但很多時候可能讓面試者搞不清你到底想問什麼,我這次面試就深受打擊,到最後面試官每個問題我都要先想半天是不是留了什麼坑),不過歸根結底自己水平差得多,還是要認真學習。言歸正傳,System類是jdk提供的一個工具類,有final修飾,不可繼承,由名字可以看出來,其中的操作多數和系統相關。其功能主要如下:

  • 標準輸入輸出,如out、in、err
  • 外部定義的屬性和環境變量的訪問,如getenv()/setenv()和getProperties()/setProperties()
  • 加載文件和類庫的方法,如load()和loadLibrary()、
  • 一個快速拷貝數組的方法:arraycopy()
  • 一些jvm操作,如gc()、runFinalization()、exit(),該部分並未在源碼的java doc中提到,可能因爲本身不建議主動調用吧。而且這幾個方法都僅僅是Runtime.getRuntime()的調用,兩者沒有區別

    下邊直接看圖,主要的方法和功能都已經列出來。

    下邊我們重點來該類是如何初始化的。

    首先在開頭我們就可以看如下代碼:

    private static native void registerNatives();
    static {
        registerNatives();
    }

    類中的靜態代碼塊調用了一個native方法registerNatives(),可以猜到該方法應該是一個入口方法,看一下注釋:通過靜態初始化註冊native方法,該方法會令vm通過調用initializeSystemClass方法來完成初始化工作。果然如此,那麼接下來我們看下initializeSystemClass方法吧:

    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()),留待以後解決吧。

    (個人學習總結原markdown文件和xmind文件見 github )

發佈了26 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章