<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>

          Java 中的對(duì)象在 JVM 中是怎么映射

          共 3456字,需瀏覽 7分鐘

           ·

          2021-10-20 15:42

          寫在前面

          Java 中的對(duì)象在 JVM 中是怎么映射的?這個(gè)話題一直想寫。但是一直沒有動(dòng)筆。后來發(fā)現(xiàn) Java 中的鎖很多問題都與這個(gè)在 JVM 中映射的對(duì)象存在著關(guān)系。還是需要搞定它。

          我們平時(shí)在寫 Java 代碼的時(shí)候,最常見的就是創(chuàng)建一個(gè)對(duì)象了。這些代碼最終都是會(huì)在虛擬機(jī)上運(yùn)行的。而一個(gè)對(duì)象最終在 JVM 中呈現(xiàn)的樣子到底是什么呢?還是非常值得我們探究一番。畢竟虛擬機(jī) HotSpot 是 C++ 實(shí)現(xiàn)的。

          探尋過程

          HotSpot 設(shè)計(jì)的一套 OOP-Klass 模型用來在 JVM 內(nèi)部進(jìn)行表示一個(gè)對(duì)象。這里我們需要提到一個(gè)詞語 OOP-Klass 二分模型。先從這個(gè)單詞的含義來理解它。OOP 是 oridinary object pointer,即普通對(duì)象指針,它是用來描述對(duì)象的實(shí)例信息。而 Klass 是代表 Java 類的 C++ 對(duì)等體,用來描述 Java 類。

          Oops模塊可以分為兩個(gè)獨(dú)立的部分:OOP 框架與 Klass 框架。

          1.探尋 OOP 框架

          在 Java 應(yīng)用程序過程中,每次創(chuàng)建一個(gè) Java 對(duì)象的時(shí)候,在 JVM 內(nèi)部也會(huì)相應(yīng)地創(chuàng)建一個(gè) OOP 對(duì)象來表示一個(gè) Java 對(duì)象。OOPS 類的共同基類為 oopDesc。

          class?oopDesc?{
          ??friend?class?VMStructs;
          ?private:
          ??volatile?markOop??_mark;
          ??union?_metadata?{
          ????wideKlassOop????_klass;
          ????narrowOop???????_compressed_klass;
          ??}?_metadata;

          在 HotSpot 中,根據(jù) JVM 內(nèi)部使用的對(duì)象業(yè)務(wù)類型,分成了多種 oopDesc 子類。每種類型的 OOP 都代表了一個(gè)在 JVM 內(nèi)部使用的特定對(duì)象模型。有點(diǎn)接口和具體實(shí)現(xiàn)類的感覺了。

          作用
          oopDescOOPS 抽象基類
          instanceOopDesc描述 Java 類的實(shí)例
          methodOopDesc描述 Java 方法
          constMethodOopDesc描述 Java 方法的只讀信息
          methodDataOopDesc描述 Java 方法的信息
          arrayOopDesc描述數(shù)組的抽象基類
          objArrayOopDesc描述容納對(duì)象( OOPS ) 元素的數(shù)組
          typeArrayOopDesc描述容納基本類型(非 OOPS )的數(shù)組
          constantPoolOopDesc描述容納類文件中常量池項(xiàng)的數(shù)組
          constantPoolCacheOopDesc描述常量池高速緩存
          klassOopDesc描述一個(gè) Java 類
          markOopDesc描述對(duì)象頭

          當(dāng)我們?cè)?Java 中使用 new 創(chuàng)建一個(gè) Java 實(shí)例對(duì)象的時(shí)候,JVM 會(huì)相應(yīng)的創(chuàng)建一個(gè)instanceOopDesc 對(duì)象來表示這個(gè) Java 對(duì)象。當(dāng)我們使用 new 創(chuàng)建一個(gè) Java 數(shù)組實(shí)例的時(shí)候,JVM 就會(huì)創(chuàng)建一個(gè) arrayOopDesc 對(duì)象來代表這個(gè)數(shù)組對(duì)象。

          一個(gè)對(duì)象在堆內(nèi)存的存儲(chǔ)布局可以分為三個(gè)部分,對(duì)象頭( Header )、實(shí)例數(shù)據(jù)(Instance Data)、和對(duì)齊填充( Padding )。而 instanceOopDesc 或者 arrayOopDesc 就是我們提到的對(duì)象頭。

          對(duì)象頭里面包含了哪些信息呢,它包含了兩部分的信息:

          • 一部分是存儲(chǔ)對(duì)象運(yùn)行時(shí)記錄信息,如哈希碼( HashCode )、GC 年代分布、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程 ID、偏向時(shí)間戳等。很多地方也稱這部分為 MarkWord。

          • 另一部分是元數(shù)據(jù)指針,指向描述類型的 Klass 對(duì)象的指針。Klass 對(duì)象包含了實(shí)例對(duì)象所屬類型的元數(shù)據(jù)(meta data)。Java 虛擬機(jī)通過這個(gè)指針來確定該對(duì)象是哪個(gè)類的實(shí)例。在運(yùn)行的時(shí)候會(huì)使用這個(gè)指針定位到位于方法區(qū)的類型信息。

          • 如果對(duì)象是一個(gè) Java 數(shù)組的話,那在對(duì)象頭中還有一塊用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù)。

          對(duì)象的對(duì)齊填充,并不是一定需要存在的。它也沒有啥特別大的作用。僅僅是起著占位符的作用。因?yàn)?HotSpot 虛擬機(jī)要求對(duì)象的起始地址必須是 8 字節(jié)的整數(shù)倍。也即任何對(duì)象的大小必須是 8 字節(jié)的整數(shù)倍。如果不夠的時(shí)候就需要這個(gè)進(jìn)行補(bǔ)齊。

          當(dāng)我們?cè)?Java 程序里面,使用 new 關(guān)鍵字創(chuàng)建對(duì)象的時(shí)候,對(duì)象的引用保存在棧上,在堆中分配對(duì)象實(shí)例。這個(gè)除了實(shí)例數(shù)據(jù)外,JVM 還會(huì)在實(shí)例數(shù)據(jù)的前面自動(dòng)加上一個(gè)對(duì)象頭 instanceOopDesc 。對(duì)象的元數(shù)據(jù)( instanceKlass )保存在方法區(qū)中。

          順便回顧一下方法區(qū)是保存什么數(shù)據(jù)的,方法區(qū)是用來存儲(chǔ)被虛擬機(jī)加載的類型信息、常量、靜態(tài)常量、即使編譯器編譯后的代碼緩存等數(shù)據(jù)。

          通過棧上引用可以訪問到 JVM 內(nèi)部表示的該對(duì)象實(shí)例(instanceOop)。當(dāng)需要調(diào)用該類的方法或者訪問該類的類變量的時(shí)候。就是通過 instanceOop 持有的類元數(shù)據(jù)指針定位到方法區(qū)中的 instanceKlass 對(duì)象來完成。

          2.探尋 Klass 框架

          Klass 數(shù)據(jù)結(jié)構(gòu):描述類型自身的布局,以及刻畫出于其他類間的關(guān)系(父類、子類、兄弟類)。Klass 是一個(gè)頂層的基類。

          這里主要說一下 instanceKlass, JVM 在運(yùn)行的時(shí)候,為每一個(gè)已經(jīng)加載的 Java 類創(chuàng)建一個(gè)instanceKlass 對(duì)象。用在 JVM 層表示 Java 類。

          instanceKlass 內(nèi)存布局如下:

          ??//類擁有的方法列表
          ??objArrayOop?????_methods;
          ??//描述方法順序
          ??typeArrayOop????_method_ordering;
          ??//實(shí)現(xiàn)的接口
          ??objArrayOop?????_local_interfaces;
          ??//繼承的接口
          ??objArrayOop?????_transitive_interfaces;
          ??//域
          ??typeArrayOop????_fields;
          ??//常量
          ??constantPoolOop?_constants;
          ??//類加載器
          ??oop?????????????_class_loader;
          ??//protected域
          ??oop?????????????_protection_domain;
          ??klassOop????????_host_klass;
          ??objArrayOop?????_signers;
          ??typeArrayOop????_inner_classes;
          ??klassOop????????_implementors?0;
          ??klassOop????????_implementors?1;
          ??typeArrayOop????_class_annotations;
          ??objArrayOop?????_fields_annotations;
          ??objArrayOop?????_methods_annotations;
          ??objArrayOop?????_methods_parameter_annotations;?
          ??objArrayOop?????_methods_default_annotations;

          以上是 OOP 塊的內(nèi)容,在 JVM 中,對(duì)象在內(nèi)存中的基本存在形式就是 OOP。

          寫在后面

          通過以上的探索,基本上有以下的共識(shí)。很重要的兩個(gè)詞匯instanceOopDesc、instanceKlass需要在腦海中留下一些印象。

          對(duì)象頭 instanceOopDesc 包含了 MarkWord 與 元數(shù)據(jù)指針。而 instanceKlass 是用來在JVM 層面表示一個(gè) Java 類的(保存在方法區(qū))。其中元數(shù)據(jù)指針就是指向 JVM 層表示一個(gè) Java 對(duì)象的 instanceKlass 。Klass 對(duì)象包含了實(shí)例對(duì)象所屬類型的元數(shù)據(jù)(meta data)。自然指向它的就被稱為了元數(shù)據(jù)指針了。

          MarkWord 里面就包含了與 Java 中鎖相關(guān)的信息了。這個(gè)后面在寫一篇專門論述。

          瀏覽 50
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  日韩无码APP | 青春草无码视频 | 欧美亚洲日韩国产 | 古装一级无遮挡A片 | 国产一区二区三区18 |