<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          馬蜂窩一面:先有Class還是先有Object?

          共 3312字,需瀏覽 7分鐘

           ·

          2022-04-18 05:58

          Java 對象模型中:

          • 所有的類都是Class類的實例,Object是類,那么Object也是Class類的一個實例。
          • 所有的類都最終繼承自Object類,Class是類,那么Class也繼承自Object。

          那到底是先有Class還是先有Object?JVM 是怎么處理這個“雞·蛋”問題呢?

          針對這個問題,我在知乎上看到了 R 大的一個回答,正好解答了我心中的疑惑,就分享出來給各位小伙伴一個參考和啟發(fā)~

          作者:RednaxelaFX,整理:沉默王二,參考鏈接:https://www.zhihu.com/question/30301819/answer/47539163


          “雞?蛋”問題通常都是通過一種叫“自舉”(bootstrap)的過程來解決的。

          “雞蛋問題”的根本矛盾就在于假定了“雞”或“蛋”的其中一個要先進入“完全可用”的狀態(tài)。而許多現(xiàn)實中被簡化為“雞蛋問題”的情況實際可以在“混沌”中把“雞”和“蛋”都初始化好,而不存在先后問題;在它們初始化的過程中,兩者都不處于“完全可用”狀態(tài),而完成初始化后它們就同時都進入了可用狀態(tài)。

          打個比方,番茄炒蛋。并不是要先把番茄完全炒好,然后把雞蛋完全炒好,然后把它們混起來;而是先炒番茄炒到半熟,再炒雞蛋炒到半熟,然后把兩個半熟的部分混在一起同時炒熟。

          對于先有Class還是先有Object這個問題來說,題主假設所有的類都是Class類的實例,Object是類,那么Object也是Class類的一個實例,這個假設就是錯的。

          java.lang.Object是一個Java類,但并不是java.lang.Class的一個實例。后者只是一個用于描述Java類與接口的、用于支持反射操作的類型。這點上Java跟其它一些更純粹的面向?qū)ο笳Z言(例如Python和Ruby)不同。

          第二個假設“所有的類都最終繼承自Object類,Class是類,那么Class也繼承自Object”是對的,java.lang.Classjava.lang.Object的派生類,前者繼承自后者。

          雖然第1個假設不對,但“雞蛋問題”仍然存在:在一個已經(jīng)啟動完畢、可以使用的Java對象系統(tǒng)里,必須要有一個java.lang.Class實例對應java.lang.Object這個類;而java.lang.Classjava.lang.Object的派生類,按“一般思維”,前者應該要在后者完成初始化之后才可以初始化…

          事實是:這些相互依賴的核心類型完全可以在“混沌”中一口氣都初始化好,然后對象系統(tǒng)的狀態(tài)才叫做完成了“bootstrap”,后面就可以按照Java對象系統(tǒng)的一般規(guī)則去運行。JVM、JavaScript、Python、Ruby等的運行時都有這樣的bootstrap過程。

          在“混沌”(boostrap過程)里,JVM可以為對象系統(tǒng)中最重要的一些核心類型先分配好內(nèi)存空間,讓它們進入[已分配空間]但[尚未完全初始化]狀態(tài)。

          此時這些對象雖然已經(jīng)分配了空間,但因為狀態(tài)還不完整所以尚不可使用。然后,通過這些分配好的空間把這些核心類型之間的引用關系串好。

          到此為止所有動作都由JVM完成,尚未執(zhí)行任何Java字節(jié)碼。然后這些核心類型就進入了[完全初始化]狀態(tài),對象系統(tǒng)就可以開始自我運行下去,也就是可以開始執(zhí)行Java字節(jié)碼來進一步完成Java系統(tǒng)的初始化了。

          在HotSpot VM里,有一個叫做“Universe”的C++類用于記錄對象系統(tǒng)的總體狀態(tài)。它有這么兩個有趣的字段記錄當前是處于bootstrapping階段還是已經(jīng)完全初始化好:

          static?bool?is_bootstrapping()??????????????????????{?return?_bootstrapping;?}
          static?bool?is_fully_initialized()??????????????????{?return?_fully_initialized;?}

          然后Universe::genesis()函數(shù)會在bootstrap階段中創(chuàng)建核心類型的對象模型,其中會調(diào)用SystemDictionary::initialize()來初始化對象系統(tǒng)的核心類型,其中會進一步跑到SystemDictionary::initialize_preloaded_classes()來創(chuàng)建java.lang.Object、java.lang.Class等核心類型。

          這個函數(shù)在加載了java.lang.Object、java.lang.Class等核心類型后會調(diào)用Universe::fixup_mirrors()來完成前面說的“把引用關系串起來”的動作:

          //?Fixup?mirrors?for?classes?loaded?before?java.lang.Class.
          //?These?calls?iterate?over?the?objects?currently?in?the?perm?gen
          //?so?calling?them?at?this?point?is?matters?(not?before?when?there
          //?are?fewer?objects?and?not?later?after?there?are?more?objects
          //?in?the?perm?gen.
          Universe::initialize_basic_type_mirrors(CHECK);
          Universe::fixup_mirrors(CHECK);

          void?Universe::fixup_mirrors(TRAPS)?{
          ??//?Bootstrap?problem:?all?classes?gets?a?mirror?(java.lang.Class?instance)?assigned?eagerly,
          ??//?but?we?cannot?do?that?for?classes?created?before?java.lang.Class?is?loaded.?Here?we?simply
          ??//?walk?over?permanent?objects?created?so?far?(mostly?classes)?and?fixup?their?mirrors.?Note
          ??//?that?the?number?of?objects?allocated?at?this?point?is?very?small.

          ??//?...
          }

          就是這樣:“Object里有一個成員變量指向Class類實例c,c保存這個Object成員、方法的名字和地址的Map映射用作反射?!鄙婕暗街黝愑羞@么幾個:

          http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/ade5be2b1758/src/share/vm/memory/universe.hpp#l399
          http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/ade5be2b1758/src/share/vm/memory/universe.cpp#l259
          http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/ade5be2b1758/src/share/vm/classfile/systemDictionary.cpp#l1814

          分享的最后,二哥要簡單說兩句,每次看 R 大的內(nèi)容,總是感覺膝蓋忍不住要跪一下,只能說寫過 JVM 的男人就是不一樣。喜歡研究 CPP 源碼的話小伙伴可以再深入學習下,一定會有所收獲。


          沒有什么使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧靜的港灣,我是不系之舟。

          推薦閱讀

          瀏覽 52
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜乱伦中文字幕 | 日韩一级操逼大片 | 久久精品系列 | 好吊无码一区二区三区 | 日本一区二区三区久久久久久久久不卡免费 |