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

          對象很大,你忍一下

          共 2279字,需瀏覽 5分鐘

           ·

          2021-12-28 22:29

          你好,我是坤哥

          上一篇Java 進(jìn)階之字節(jié)碼剖析中我曾經(jīng)提到這么一段話

          int[128][2] ,int[256] 這兩個(gè)數(shù)組看起來一樣,但實(shí)際上前者比后者多了 246% 的額外開銷

          針對這句話我收到了幾位讀者的私信,表示不明白為啥不過一個(gè)簡單的二維數(shù)組會(huì)有這么大的開銷,本來這個(gè)問題在我正在寫的類加載機(jī)制中有詳述,不過文章還沒寫完(估計(jì)本周發(fā)),所以我專門抽出這個(gè)問題探討一下,五分鐘就能看懂

          Java 對象模型

          HotSpot JVM 底層使用名為 oops (Ordinary Object Pointers) 的數(shù)據(jù)結(jié)構(gòu)來表示對象的對象頭

          class?oopDesc?{
          ??friend?class?VMStructs;
          ??private:
          ????volatile?markOop??_mark;
          ????union?_metadata?{
          ??????Klass*??????_klass;
          ??????narrowKlass?_compressed_klass;
          ????}?_metadata;
          ????...
          }

          JVM 每創(chuàng)建一個(gè)對象,相當(dāng)于創(chuàng)建了一個(gè) oopDesc 的對象,即 instanceOopDesc 來表示這個(gè)對象,保存在堆中,如下圖所示

          可以看到 Java 對應(yīng)主要由以下三部分組成

          • 對象頭(Header)

          • 對象實(shí)例數(shù)據(jù)(instance data)

          • 對齊填充(Padding)

          其中對象頭又包含三個(gè)部分

          • markWord: ?即 _mark:markOop,用于存儲對象運(yùn)行時(shí)的數(shù)據(jù),好比 HashCode、鎖狀態(tài)標(biāo)志、GC分代年齡等。這部分在 64 位操作系統(tǒng)下占 8 字節(jié),32 位操作系統(tǒng)下占 4 字節(jié)

          • 指針:指向方法區(qū)中的類元數(shù)據(jù)(類信息)的指針,這部分就涉及到指針壓縮的概念,在開啟指針壓縮的狀況下占 4 字節(jié),未開啟狀況下占 8 字節(jié),默認(rèn)是開啟的

          • 數(shù)組長度:這部分只有是數(shù)組對象才有,若是非數(shù)組對象就沒這部分。這部分占 4 字節(jié)。

          除此之外對象還有兩個(gè)部分值得我們注意

          • 對象實(shí)例數(shù)據(jù)(instanceData): 用于存儲對象中的各種類型的字段信息(包括從父類繼承來的)

          • 對齊填充:Java 對象大小默認(rèn)按 8 字節(jié)對齊的,如果「對象頭」+「對象實(shí)際數(shù)據(jù)」不足8的位數(shù),對齊填充會(huì)補(bǔ)齊相應(yīng)的字節(jié)以讓對象大小達(dá)到 8 的倍數(shù)

          Java 數(shù)組大小

          知道了對象模型的表示,再來看數(shù)組的大小,首先必須明確兩點(diǎn)

          1. 在 Java 中數(shù)組是一種特殊的對象(也是對象,也有對象頭)

          2. 一個(gè)多維數(shù)組是一個(gè)簡單數(shù)組的數(shù)組, ?例如,一個(gè)二維數(shù)組的每一行都是一個(gè)獨(dú)立的數(shù)組對象

          接下來我們來看看一維數(shù)組 int[256] ?在內(nèi)存中有多大,一維數(shù)組其實(shí)可以認(rèn)為是普通的對象,首先對象頭可以知道是 8(markword) + 4(kclass) + 4(數(shù)組長度)= 16 字節(jié),對象實(shí)際數(shù)據(jù)大小為 256 * 4(int 大小為 4 個(gè)字節(jié)) = 1024 ?字節(jié),所以此時(shí)總的字節(jié)數(shù)為 16 + 1024 = 1040 字節(jié),是 8 的位數(shù)(1040/8 = 130),所以 padding 為 0, 也就是說 int[256] 一維數(shù)組的字節(jié)大小為 1040 字節(jié)

          再來看一下二維數(shù)組 int[128][2] 的大小,我們知道在 C 語言中二維數(shù)組(事實(shí)上是任何多維數(shù)組)本質(zhì)上是一維數(shù)組通過指針操作來實(shí)現(xiàn)的,但在 Java 中多維數(shù)組是由一系列的嵌套數(shù)組組成,也就是說對于二維數(shù)組而言,每一行(int[0][…],int[1][…],…,int[127][…])都對應(yīng)一個(gè)數(shù)組對象,都需要額外的開銷,一圖勝千言,如下所示

          先來看左邊的對象大小:

          數(shù)組的每一行 int[0],int[1],..int[127] 其實(shí)都是指向數(shù)組的指針,為 4 個(gè)字節(jié),所以左邊對象占用空間大小為 16 + 4 * 128 = 528,是 8 的倍數(shù)(528/8 = 66),所以 padding 為 0,所以總大小為 528

          再來看左邊的 int[0] 等指向的數(shù)組對象大?。?/p>

          由于左邊每個(gè)行數(shù)組的指向都指向了兩個(gè)元素的數(shù)組(int[x][0],int[x][1]),它們的對象大小為 ?16 + 4 + 4 = 24,是 8 的倍數(shù),所以 padding 為 0 ,而總共有 128 個(gè)這樣的對象,所以右邊總的對象大小為 128 * 24 = 3072

          由此可知 int[128][2] 對象大小為 528 + 3072 = 3600 字節(jié),比一維數(shù)組 int[256](1024 字節(jié))多了 246% !

          上述計(jì)算的是否正確呢,我們可以用 JDK 自帶的 ObjectSizeCalculator 來計(jì)算一下,如下:

          與我們的計(jì)算結(jié)果完全一致!

          其實(shí)不光是二維數(shù)組,包括字節(jié)串,普通的對象開銷也一般會(huì)比對象實(shí)際數(shù)據(jù)大幾倍,到此我相信你不難明白上一篇中開頭這樣一段話的含義了:kafka 中為啥要使用 pageCache 了, 因?yàn)槿绻挥庙摼彺?,而是?JVM 進(jìn)程中的緩存,對象的內(nèi)存開銷會(huì)非常大(通常是真實(shí)數(shù)據(jù)大小的幾倍甚至更多)


          推薦閱讀:

          常見消息中間件大 PK

          如出一轍。。。

          為什么CTO不寫代碼,還這么牛逼?



          關(guān)互聯(lián)網(wǎng)全棧架構(gòu),價(jià)。

          瀏覽 36
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  国产成人精品一级毛片 | 第一页欧美 | 77无码 | 大香蕉精品在线视频 | 中国无码免费 |